release winning entries of IOCCC28 under the year 2024
Congratulations to: * 2024/anders - Prize in sound coding - layered music generator * 2024/burton - Prize in pentagrammatology - wordle hard mode solver * 2024/cable1 - Prize in bot talk - LLM inference engine * 2024/cable2 - Prize in murky waters - salmon recipe * 2024/carlini - Prize in perfect timing - Intel 4004 emulation * 2024/codemeow - Prize in tray planting - bonsai generator * 2024/endoh1 - Prize in patient pointillism - slow ray tracer in CPP * 2024/endoh2 - Prize in solid body physics - rotating rigid body simulation * 2024/ferguson1 - Prize in diabolical logistics - Oregon trail pact with the devil * 2024/ferguson2 - Prize in yil-tas - Navajo code talker translator * 2024/howe - Nice accent eh-ward - mini vi * 2024/kramer - Prize in linguistic arithmetic - natural language numerical calculator * 2024/kurdyukov1 - Prize in phased periodicity - phase of the Moon * 2024/kurdyukov2 - Prize in art restoration - JPEG artifact removal * 2024/kurdyukov3 - Prize in virtual quietus - gaming VM and doom * 2024/kurdyukov4 - Prize in embiggening - encode without literals * 2024/maffiodo - Prize in creative interpretation - Jav\*script interpreter * 2024/mills - Prize in ℤ₃ - Infocom v3 story interpreter * 2024/stedolan - Best one liner - icon from MD5 * 2024/straadt - Prize in imitative rebooting - OpenRISC CPU and Linux * 2024/tmarrec - Prize in cyclonic coding - 3D tornado simulation * 2024/tompng - Prize in quasi bijection - vortex encryptor decryptor * 2024/weaver - Sur prize - rickroll Ran `make update` to perform the above. new file: 2024/burton/.entry.json
This commit is contained in:
1 parent
10512e6c79
commit
09750f8899
443 files changed
+182938
-231
No files matched your search
@@ -319,3 +319,26 @@
|
||||
2020/otterness
|
||||
2020/tsoj
|
||||
2020/yang
|
||||
2024/anders
|
||||
2024/burton
|
||||
2024/cable1
|
||||
2024/cable2
|
||||
2024/carlini
|
||||
2024/codemeow
|
||||
2024/endoh1
|
||||
2024/endoh2
|
||||
2024/ferguson1
|
||||
2024/ferguson2
|
||||
2024/howe
|
||||
2024/kramer
|
||||
2024/kurdyukov1
|
||||
2024/kurdyukov2
|
||||
2024/kurdyukov3
|
||||
2024/kurdyukov4
|
||||
2024/maffiodo
|
||||
2024/mills
|
||||
2024/stedolan
|
||||
2024/straadt
|
||||
2024/tmarrec
|
||||
2024/tompng
|
||||
2024/weaver
|
||||
Binary file not shown.
Binary file not shown.
+1
-1
@@ -462,7 +462,7 @@
|
||||
|
||||
<h2 id="author">Author:</h2>
|
||||
<ul>
|
||||
<li>Name: <a href="../../authors.html#Anthony_C_Howe">Anthony C. Howe</a><br>
|
||||
<li>Name: <a href="../../authors.html#Anthony_C_Howe">Anthony C Howe</a><br>
|
||||
Location: <a href="../../location.html#CA">CA</a> - <em>Canada</em></li>
|
||||
</ul>
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
+1
-1
@@ -462,7 +462,7 @@
|
||||
|
||||
<h2 id="author">Author:</h2>
|
||||
<ul>
|
||||
<li>Name: <a href="../../authors.html#Anthony_C_Howe">Anthony C. Howe</a><br>
|
||||
<li>Name: <a href="../../authors.html#Anthony_C_Howe">Anthony C Howe</a><br>
|
||||
Location: <a href="../../location.html#CA">CA</a> - <em>Canada</em></li>
|
||||
</ul>
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
+1
-1
@@ -462,7 +462,7 @@
|
||||
|
||||
<h2 id="author">Author:</h2>
|
||||
<ul>
|
||||
<li>Name: <a href="../../authors.html#Anthony_C_Howe">Anthony C. Howe</a><br>
|
||||
<li>Name: <a href="../../authors.html#Anthony_C_Howe">Anthony C Howe</a><br>
|
||||
Location: <a href="../../location.html#CA">CA</a> - <em>Canada</em></li>
|
||||
</ul>
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -462,7 +462,7 @@
|
||||
|
||||
<h2 id="author">Author:</h2>
|
||||
<ul>
|
||||
<li>Name: <a href="../../authors.html#Anthony_C_Howe">Anthony C. Howe</a><br>
|
||||
<li>Name: <a href="../../authors.html#Anthony_C_Howe">Anthony C Howe</a><br>
|
||||
Location: <a href="../../location.html#CA">CA</a> - <em>Canada</em></li>
|
||||
</ul>
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -462,7 +462,7 @@
|
||||
|
||||
<h2 id="author">Author:</h2>
|
||||
<ul>
|
||||
<li>Name: <a href="../../authors.html#Anthony_C_Howe">Anthony C. Howe</a><br>
|
||||
<li>Name: <a href="../../authors.html#Anthony_C_Howe">Anthony C Howe</a><br>
|
||||
Location: <a href="../../location.html#CA">CA</a> - <em>Canada</em></li>
|
||||
</ul>
|
||||
|
||||
|
||||
Binary file not shown.
@@ -462,7 +462,7 @@
|
||||
|
||||
<h2 id="author">Author:</h2>
|
||||
<ul>
|
||||
<li>Name: <a href="../../authors.html#Vincent_Weaver">Vincent Weaver</a><br>
|
||||
<li>Name: <a href="../../authors.html#Vincent_Weaver">Vince Weaver</a><br>
|
||||
Location: <a href="../../location.html#US">US</a> - <em>United States of America</em> (<em>United States</em>)</li>
|
||||
</ul>
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -462,7 +462,7 @@
|
||||
|
||||
<h2 id="author">Author:</h2>
|
||||
<ul>
|
||||
<li>Name: <a href="../../authors.html#Anthony_C_Howe">Anthony C. Howe</a><br>
|
||||
<li>Name: <a href="../../authors.html#Anthony_C_Howe">Anthony C Howe</a><br>
|
||||
Location: <a href="../../location.html#CA">CA</a> - <em>Canada</em></li>
|
||||
</ul>
|
||||
|
||||
|
||||
Binary file not shown.
+41
-13
@@ -60,6 +60,7 @@
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../years.html" class="sub-item-link">
|
||||
Winning entries
|
||||
@@ -95,6 +96,7 @@
|
||||
Updating author info
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -104,6 +106,7 @@
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../news.html" class="sub-item-link">
|
||||
News
|
||||
@@ -117,8 +120,14 @@
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../next/index.html" class="sub-item-link">
|
||||
Rules and guidelines
|
||||
<a href="../next/rules.html" class="sub-item-link">
|
||||
IOCCC rules
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../next/guidelines.html" class="sub-item-link">
|
||||
IOCCC guidelines
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -143,9 +152,10 @@
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../faq.html" class="sub-item-link">
|
||||
Frequently Asked Questions
|
||||
Frequently asked questions
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -182,12 +192,19 @@
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../index.html" class="sub-item-link">
|
||||
Home page
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../social.html" class="sub-item-link">
|
||||
IOCCC social media
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../about.html" class="sub-item-link">
|
||||
About the IOCCC
|
||||
@@ -196,7 +213,7 @@
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../judges.html" class="sub-item-link">
|
||||
The Judges
|
||||
The judges
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -276,6 +293,7 @@
|
||||
<a class="mobile-submenu-item" href="../thanks-for-help.html">
|
||||
Thanks for the help
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -294,8 +312,12 @@
|
||||
Contest status
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../next/index.html">
|
||||
Rules and guidelines
|
||||
<a class="mobile-submenu-item" href="../next/rules.html">
|
||||
IOCCC rules
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../next/guidelines.html">
|
||||
IOCCC guidelines
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../markdown.html">
|
||||
@@ -305,6 +327,7 @@
|
||||
<a class="mobile-submenu-item" href="../SECURITY.html">
|
||||
Security policy
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -315,7 +338,7 @@
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../faq.html">
|
||||
Frequently Asked Questions
|
||||
Frequently asked questions
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../quick-start.html#enter">
|
||||
@@ -347,17 +370,22 @@
|
||||
Home page
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../social.html">
|
||||
IOCCC social media
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../about.html">
|
||||
About the IOCCC
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../judges.html">
|
||||
The Judges
|
||||
The judges
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../contact.html">
|
||||
Contact us
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -409,17 +437,17 @@
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/header.default.html -->
|
||||
<!-- START: this line starts content from: inc/navbar.year.last.html -->
|
||||
<!-- START: this line starts content from: inc/navbar.year.mid.html -->
|
||||
|
||||
<div class="navbar">
|
||||
<a class="Left" href="../2019/index.html">← 2019</a>
|
||||
<a class="Left" href="../years.html">↑ top ↑</a>
|
||||
<a class="Left Disabled" href="#">No next</a>
|
||||
<a class="Left" href="../2024/index.html">2024 →</a>
|
||||
<a class="Right" href="#inventory">Inventory</a>
|
||||
<a class="Right" href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fwww.ioccc.org%2F2020%2Findex.html">✓</a>
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/navbar.year.last.html -->
|
||||
<!-- END: this line ends content from: inc/navbar.year.mid.html -->
|
||||
<!-- START: this line starts content from: inc/before-content.default.html -->
|
||||
|
||||
<div class="content" id="content">
|
||||
@@ -532,7 +560,7 @@ Jump to: <a href="#">top</a>
|
||||
|
||||
<!--
|
||||
|
||||
Copyright © 1984-2024 by Landon Curt Noll. All Rights Reserved.
|
||||
Copyright © 1984-2025 by Landon Curt Noll. All Rights Reserved.
|
||||
|
||||
You are free to share and adapt this file under the terms of this license:
|
||||
|
||||
@@ -546,7 +574,7 @@ Jump to: <a href="#">top</a>
|
||||
|
||||
<div class="footer">
|
||||
|
||||
<div id="copyright"><h3>Copyright © 1984-2024 by Landon Curt Noll:
|
||||
<div id="copyright"><h3>Copyright © 1984-2025 by Landon Curt Noll:
|
||||
<a href="https://creativecommons.org/faq/#what-does-some-rights-reserved-mean"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer">Some Rights Reserved</a></h3>
|
||||
|
||||
Binary file not shown.
@@ -438,19 +438,19 @@
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/header.default.html -->
|
||||
<!-- START: this line starts content from: inc/navbar.last.html -->
|
||||
<!-- START: this line starts content from: inc/navbar.mid.html -->
|
||||
|
||||
<div class="navbar">
|
||||
<a class="Left" href="../tsoj/index.html">← 2020/tsoj</a>
|
||||
<a class="Left" href="../index.html">↑ 2020 ↑</a>
|
||||
<a class="Left Disabled" href="#">last entry</a>
|
||||
<a class="Left" href="../../2024/anders/index.html">2024/anders →</a>
|
||||
<a class="Right" href="https://github.com/ioccc-src/winner/blob/master/2020/yang/prog.c">C code</a>
|
||||
<a class="Right" href="https://github.com/ioccc-src/winner/blob/master/2020/yang/Makefile">Makefile</a>
|
||||
<a class="Right" href="#inventory">Inventory</a>
|
||||
<a class="Right" href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fwww.ioccc.org%2F2020%2Fyang%2Findex.html">✓</a>
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/navbar.last.html -->
|
||||
<!-- END: this line ends content from: inc/navbar.mid.html -->
|
||||
<!-- START: this line starts content from: inc/before-content.default.html -->
|
||||
|
||||
<div class="content" id="content">
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
2024/2024.tar.bz2
|
||||
2024/.filelist
|
||||
2024/guidelines.html
|
||||
2024/guidelines.md
|
||||
2024/index.html
|
||||
2024/Makefile
|
||||
2024/README.md
|
||||
2024/rules.html
|
||||
2024/rules.md
|
||||
2024/.year
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
2024/anders
|
||||
2024/burton
|
||||
2024/cable1
|
||||
2024/cable2
|
||||
2024/carlini
|
||||
2024/codemeow
|
||||
2024/endoh1
|
||||
2024/endoh2
|
||||
2024/ferguson1
|
||||
2024/ferguson2
|
||||
2024/howe
|
||||
2024/kramer
|
||||
2024/kurdyukov1
|
||||
2024/kurdyukov2
|
||||
2024/kurdyukov3
|
||||
2024/kurdyukov4
|
||||
2024/maffiodo
|
||||
2024/mills
|
||||
2024/stedolan
|
||||
2024/straadt
|
||||
2024/tmarrec
|
||||
2024/tompng
|
||||
2024/weaver
|
||||
Binary file not shown.
+510
@@ -0,0 +1,510 @@
|
||||
#!/usr/bin/env make
|
||||
#
|
||||
# 2024 Makefile
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# IOCCC winning entry code may not work on your system. What was liked/allowed
|
||||
# and worked in the past may no longer be liked/allowed or compile/run today.
|
||||
#
|
||||
# Bug fixes, corrections and typo fixes are VERY WELCOME. If you see a problem,
|
||||
# first check this URL for a list of known bugs and (mis)features of IOCCC entries:
|
||||
#
|
||||
# https://www.ioccc.org/bugs.html
|
||||
#
|
||||
# GitHub pull requests are welcome! Please see the above URL for details.
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
# This file is Copyright (c) 2024 by Landon Curt Noll. All Rights Reserved.
|
||||
# You are free to share and adapt this file under the terms of this license:
|
||||
#
|
||||
# Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
||||
#
|
||||
# For more information, see: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
|
||||
#############################
|
||||
# shell used by this Makefile
|
||||
#############################
|
||||
|
||||
SHELL= bash
|
||||
|
||||
#######################
|
||||
# common tool locations
|
||||
#######################
|
||||
|
||||
include ../var.mk
|
||||
|
||||
|
||||
###############
|
||||
# IOCCC entries
|
||||
###############
|
||||
|
||||
# 1st - DO NOT REMOVE THIS LINE - bin/new-dir.sh uses this line #
|
||||
ENTRIES= anders burton cable1 cable2 carlini codemeow endoh1 endoh2 \
|
||||
ferguson1 ferguson2 howe kramer kurdyukov1 kurdyukov2 kurdyukov3 \
|
||||
kurdyukov4 maffiodo mills stedolan straadt tmarrec tompng weaver
|
||||
# 2nd - DO NOT REMOVE THIS LINE - bin/new-dir.sh uses this line #
|
||||
|
||||
YEAR= 2024
|
||||
|
||||
|
||||
###################
|
||||
# build all entries
|
||||
###################
|
||||
|
||||
all:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
.PHONY: all alt data everything diff_orig_prog diff_prog_orig \
|
||||
diff_alt_prog diff_prog_alt diff_orig_alt diff_alt_orig \
|
||||
clean clobber install genpath clang-format add_dir love haste \
|
||||
waste maker easter_egg sandwich supernova more_magic magic charon pluto
|
||||
|
||||
# alternative executable
|
||||
#
|
||||
alt:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
# data files
|
||||
#
|
||||
data:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
# both all and alt
|
||||
#
|
||||
everything:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
|
||||
#####################
|
||||
# make a difference #
|
||||
#####################
|
||||
|
||||
# diff orig source and source
|
||||
#
|
||||
diff_orig_prog:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
# diff source and orig source
|
||||
#
|
||||
diff_prog_orig:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
# diff alt source and source
|
||||
#
|
||||
diff_alt_prog:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
# diff source and alt source
|
||||
#
|
||||
diff_prog_alt:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
# diff orig and alt
|
||||
#
|
||||
diff_orig_alt:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
# diff alt and orig
|
||||
diff_alt_orig:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
|
||||
###############
|
||||
# utility rules
|
||||
###############
|
||||
|
||||
clean:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
clobber:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
genpath:
|
||||
@echo '=-=-= IOCCC begin make $@ =-=-='
|
||||
@${RM} -f .tmp.genpath
|
||||
@${TOUCH} .tmp.genpath
|
||||
@-for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "${YEAR}/$$i" >> .tmp.genpath; \
|
||||
${RM} -f "$$i/.tmp.genpath"; \
|
||||
echo "${YEAR}/$$i" >> "$$i/.tmp.genpath"; \
|
||||
if ${CMP} -s "$$i/.tmp.genpath" "$$i/.path"; then \
|
||||
${RM} -f "$$i/.tmp.genpath"; \
|
||||
echo "$$i/.path already up to date"; \
|
||||
else \
|
||||
${MV} -f "$$i/.tmp.genpath" "$$i/.path"; \
|
||||
${CHMOD} 0444 "$$i/.path"; \
|
||||
echo "updated $$i/.path"; \
|
||||
fi; \
|
||||
fi; \
|
||||
done
|
||||
@-if ${CMP} -s .tmp.genpath .year; then \
|
||||
${RM} -f .tmp.genpath; \
|
||||
echo ".year already up to date"; \
|
||||
else \
|
||||
${MV} -f .tmp.genpath .year; \
|
||||
${CHMOD} 0444 .year; \
|
||||
echo "updated .year"; \
|
||||
fi
|
||||
@echo '=-=-= IOCCC complete make $@ =-=-='
|
||||
|
||||
|
||||
#############################################################
|
||||
# NOTE: 'Don't Panic' if you don't understand the stuff below
|
||||
#############################################################
|
||||
|
||||
# new_entry - add a new entry directory name to the ${ENTRIES} Makefile variable
|
||||
#
|
||||
# Add ${NEW_ENTRY} to the list of ${ENTRIES} and output Makefile lines to set updated
|
||||
# ${ENTRIES} Makefile variable.
|
||||
#
|
||||
# If list of ${ENTRIES} is long, we format it into a multi-line value setting with required
|
||||
# backslashes and indentation. Duplicate values are removed and the initial 'submit.[0-9]*' (used
|
||||
# during judging) is removed. The words (directory names) in ${ENTRIES} are sorted in C dictionary order.
|
||||
#
|
||||
# This rule is used by the bin/new-dir.sh shell script via:
|
||||
#
|
||||
# make -C ${YEAR} new_entry NEW_ENTRY=curds
|
||||
#
|
||||
new_entry:
|
||||
@if [[ -z "${NEW_ENTRY}" ]]; then echo "$@: ERROR: NEW_ENTRY is empty" 1>&2; exit 1; fi
|
||||
@if [[ ! -d "${NEW_ENTRY}" ]]; then echo "$@: ERROR: not a directory: ${YEAR}/${NEW_ENTRY}" 1>&2; exit 2; fi
|
||||
@(echo -n 'ENTRIES= '; \
|
||||
(for dir in ${ENTRIES} ${NEW_ENTRY}; do \
|
||||
if [[ $$dir != 'submit.[0-9]*' ]]; then echo "$$dir"; fi; \
|
||||
done | \
|
||||
LANG=C ${SORT} -d -u; \
|
||||
) \
|
||||
) | \
|
||||
${FMT} | \
|
||||
${SED} -e '2,$$s/^/\t/' -e 's/$$/ \\/' -e '$$s/ \\//'
|
||||
|
||||
|
||||
########################
|
||||
# extended utility rules
|
||||
########################
|
||||
|
||||
install:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
clang-format:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
|
||||
##################
|
||||
# 1337 hacker rulz
|
||||
##################
|
||||
|
||||
love:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
haste:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
waste:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
maker:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
easter_egg:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
sandwich:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
|
||||
# The IOCCC resident astronomer states
|
||||
#
|
||||
supernova:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
more_magic:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
magic:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
charon:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
|
||||
pluto:
|
||||
@echo '=-=-= ${YEAR} begin make $@ =-=-='
|
||||
@echo
|
||||
@for i in ${ENTRIES}; do \
|
||||
if [[ -d $$i ]]; then \
|
||||
echo "=-= start ${YEAR}/$$i =-="; \
|
||||
echo "(cd $$i && ${MAKE} $@)"; \
|
||||
(cd $$i && ${MAKE} $@); \
|
||||
echo "=-= end ${YEAR}/$$i =-="; \
|
||||
echo; \
|
||||
fi; \
|
||||
done
|
||||
@echo '=-=-= ${YEAR} complete make $@ =-=-='
|
||||
+389
@@ -0,0 +1,389 @@
|
||||
# Twenty Eighth International Obfuscated C Code Contest
|
||||
|
||||
|
||||
## Where to start
|
||||
|
||||
See below for links to the [2024 winning IOCCC entries](#inventory).
|
||||
|
||||
Check out the `index.html` web pages for each winning entry. They have
|
||||
most of the information you need to compile and run the winning program.
|
||||
Take a look at the winning source code and try to figure out how it works.
|
||||
You might also want to check out the author’s remarks for even more details.
|
||||
|
||||
You may [download all winning entries](2024.tar.bz2) in the form
|
||||
of a compressed tarball, for this year's contest.
|
||||
|
||||
|
||||
## General remarks on this contest
|
||||
|
||||
This year marked the [40th anniversary of the IOCCC](../faq.html#ioccc_start).
|
||||
The **IOCCC28** opened submissions from **2025-03-05 23:19:17.131107 UTC** to **2025-06-05
|
||||
04:03:02.010099 UTC** after a 4 year pause.
|
||||
|
||||
A significant portion of those 4 years was an effort by a [number of people](../thanks-for-help.html),
|
||||
with over 6168+ commits, to rebuild the [Official IOCCC website](../index.html)
|
||||
in what became known as the **Great Fork Merge**.
|
||||
|
||||
Another portion of those 4 years went into retooling the IOCCC, including the creation of
|
||||
the [mkiocccentry toolkit](https://github.com/ioccc-src/mkiocccentry), a new
|
||||
[IOCCC registration process](../next/register.html), and a new
|
||||
[IOCCC submit server](https://submit.ioccc.org/) (which may not be up if the contest is closed).
|
||||
|
||||
The **major motivation** for the above was to:
|
||||
|
||||
* Present [IOCCC winners](../years.html) that that honors the contributions of all of the [winning authors](../authors.html) from [around the world](../location.html),
|
||||
|
||||
* Reduce the administrative effort required by the [IOCCC Judges](../judges.html) to run the contest, and
|
||||
|
||||
* Minimize the time between when the winners of the IOCCC are selected and when the source is made available.
|
||||
|
||||
On the last point, for **IOCCC28** the Judging started on **2025-06-05 04:03:02.010099 UTC** and then the winners were selected by the [IOCCC Judges](../judges.html) on **2025-07-07 20:05:07.000000 UTC**:
|
||||
|
||||
* Winners were announced during a live the [Our Favorite Universe](https://www.youtube.com/@OurFavoriteUniverse) YouTube Channel that started on **2025-08-02 18:00:00.000000 UTC**
|
||||
|
||||
* Near the end of the 2 hour XXX-add-show-URL-here-XXX YouTube show, the **source code** of the [IOCCC28 winning entries](#inventory) was published on [IOCCC GitHub winner repo](https://github.com/ioccc-src/winner) and on the [Official IOCCC website](../index.html).
|
||||
|
||||
**No longer will there be many months** between when the winners are
|
||||
announced and their source code is made available. For **IOCCC28**
|
||||
the time was **less than 2 hours**. :-)
|
||||
|
||||
|
||||
### Increased submission quantity and quality
|
||||
|
||||
The submissions to **IOCCC28** were remarkable when compared with previous contests, in both the
|
||||
**increased quantity and quality** of the submissions. As a result the judging process for **IOCCC28**
|
||||
was more challenging and required greater effort. Thankfully due to the above mentioned improvements,
|
||||
the judging process **took only 33 days**. Under the previous system it **would have taken much longer**!
|
||||
|
||||
One thing that began to emerge after we exits the early rounds of judging and entered the middle rounds
|
||||
of judging was that we were very likely to have more winning entries than in previous contests.
|
||||
Even so, the final rounds of judging required more rounds and tool longer than in any previous IOCCC.
|
||||
|
||||
At the end of the final round of the final rounds of judging, we had a record **23 winners of IOCCC28**,
|
||||
eclipsing the record of 15 winners!
|
||||
|
||||
While we suspect that the 4 year gap between **IOCCC27** and **IOCCC28** allowed people extra
|
||||
time to improve their submissions, we also believe that people submitting to the IOCCC have
|
||||
adept in obfuscation and have become more skilled in the programming in the C language.
|
||||
|
||||
|
||||
### Code size and Rule 2
|
||||
|
||||
We were pleased to observe that while the [IOCCC size limit](../faq.html#size_rule_history)
|
||||
increased by about 21%, we received many submissions that were well under the new
|
||||
[Rule 2 size limit](../next/rules.html#rule2) including a fair number of quality
|
||||
small and medium sized submissions. Half of the **IOCCC28 winners** were less than
|
||||
_2/3 of the size limit_, and 10 of the **IOCCC28 winners** were less than
|
||||
_1/2 of the size limit_!
|
||||
|
||||
**IMPORTANT NOTE**: The [IOCCC size limit](../faq.html#size_rule_history) increase for **IOCCC28**
|
||||
was the first size increase in over 10 years. Given the quality of submissions we received
|
||||
that were well under the limit, we do **NOT** expect to change the
|
||||
[Rule 2 size limit](../next/rules.html#rule2) for **at least another 10 years** (and likely longer).
|
||||
|
||||
**IMPORTANT HINT**: Only 3 of 23 the **IOCCC28 winners** came close to the [Rule 2 size limit](../next/rules.html#rule2).
|
||||
Large code size isn't everything. :-) Those submitting to future contents should
|
||||
**take a careful note** of that fact.
|
||||
|
||||
|
||||
### Rules and Guidelines for this contest
|
||||
|
||||
Here are the final versions of the IOCCC rules and guidelines that were in effect for this contest:
|
||||
|
||||
* [2024 rules](rules.html) version **28.30 2025-03-03**
|
||||
* [2024 guidelines](guidelines.html) version **28.47 2025-03-15**
|
||||
|
||||
|
||||
### Looking forward to the next contest
|
||||
|
||||
The [IOCCC Judges](../judges.html) realize that the [IOCCC rules](../next/rules.html) and
|
||||
the [IOCCC guidelines](../next/guidelines.html) need to be **greatly improved and streamlined**.
|
||||
We decided to not overhaul them for **IOCCC28** so as to **NOT** delay the opening of the contest.
|
||||
|
||||
After the [IOCCC Judges](../judges.html) take a short _IOCCC Vacation_ (we have been working solid
|
||||
on **IOCCC28** since **2020 Dec 30**), we plan to update, improve and streamline the
|
||||
[IOCCC rules](../next/rules.html) and the [IOCCC guidelines](../next/guidelines.html) for **IOCCC29**.
|
||||
Then we will address whatever bug fixes in the form of GitHub Pull Requests to both the
|
||||
[IOCCC GitHub winner repo](https://github.com/ioccc-src/winner) and the
|
||||
[mkiocccentry toolkit repo](https://github.com/ioccc-src/mkiocccentry) that may be pending.
|
||||
|
||||
Once we are all caught up, we will set the opening date for **IOCCC29**. It is our plan
|
||||
to open **IOCCC29** sometime in **2025 December**.
|
||||
|
||||
|
||||
## Remarks on some of the winning entries
|
||||
|
||||
There were a number of remarkable winning entries for **IOCCC28**. We wish to call
|
||||
attention to a few of them:
|
||||
|
||||
* [2024/kurdyukov1](kurdyukov1/index.html)
|
||||
|
||||
This entry is a fun revisit of the theme of [2000/natori](../2000/natori/index.html),
|
||||
only better and without using any floating point arithmetic. You are invited
|
||||
to try and understand why the constant `2551443` is common to both entries.
|
||||
|
||||
* [2024/cable1](cable1/index.html)
|
||||
|
||||
This entry claims to be "_the world’s smallest LLM (large language
|
||||
model) inference engine_": running open-source model based on Meta’s
|
||||
LLaMA 2 with 7 billion parameters. After downloading the model via the
|
||||
[2024/cable1/get_model.sh](%%REPO_URL%%/2024/cable1/get_model.sh) script,
|
||||
we invite you explore this **ChatIOCCC** tool. While not super fast,
|
||||
the tool's output can be amusing.
|
||||
|
||||
You might wish to ask **ChatIOCCC**: "_Why did this entry win IOCCC28?_"?
|
||||
|
||||
We encourage you to read and understand the
|
||||
[2024/cable1/prog.c source code](%%REPO_URL%%/2024/cable1/prog.c). Then see
|
||||
if the **ChatIOCCC** tool can offer any new, or even correct insights
|
||||
into the code's obfuscation. :-)
|
||||
|
||||
* [2024/howe](howe/index.html)
|
||||
|
||||
"_Eh_"? The source code, with its UTF-8 conforming accent gives you a
|
||||
polite editor that is more functional an `ed(1)`.
|
||||
|
||||
We invite you to use the program to view the UTF-8 fun in the
|
||||
[2024/howe/prog.c source code](%%REPO_URL%%/2024/howe/prog.c).
|
||||
|
||||
**HINT to emacs users**: type **Q** or press **CTRL+C** to exit. 🤓
|
||||
|
||||
* [2024/stedolan](stedolan/index.html)
|
||||
|
||||
When you view the [prog.c source code](%%REPO_URL%%/2024/stedolan/prog.c),
|
||||
notice magic numbers. This **one liner** packs a significant amount
|
||||
of obfuscation in only 135 bytes!
|
||||
|
||||
Try giving 10 hex digits to standard input of the program. Then try a
|
||||
different hex digits value. Then feed the MD5 hash of the
|
||||
[2024/stedolan/prog.c source code](%%REPO_URL%%/2024/stedolan/prog.c) and
|
||||
"_C_" what happens. :-)
|
||||
|
||||
* [2024/endoh1](endoh1/index.html)
|
||||
|
||||
The [2024/endoh1/try.sh](%%REPO_URL%%/2024/endoh1/try.sh) will carry you on
|
||||
a journey that tests your patience as well as the patience of the C-preprocessor.
|
||||
|
||||
Building a 8x8 image requires order of 20 seconds of C-preprocessor
|
||||
time, when running 6 jobs on 4 CPU cores in parallel. Unfortunately,
|
||||
with such a tiny image, it is hard to appreciate the image being rendered.
|
||||
|
||||
So you might try building a 32x32 form of the image, invoking the
|
||||
C-preprocessor 1024 times. When using 6 jobs on 4 CPU cores in parallel,
|
||||
this might take about 5.5 minutes to complete. However, the small image
|
||||
only gives you a hint of the image being rendered.
|
||||
|
||||
If you have the time you might try building a 128x128 image, invoking
|
||||
the C-preprocessor 16384 times. With 6 jobs on 4 CPU cores in parallel,
|
||||
this will take about 1.5 hours. At this scale you might consider it
|
||||
worthwhile to render a more detailed image.
|
||||
|
||||
Using 6 jobs on 4 CPU cores in parallel, to build a 512x512 image invoking
|
||||
the C-preprocessor 262144 times over a period of about 23.5 hours, you
|
||||
will be given an image with a reasonable amount of detail to appreciate
|
||||
what is being rendered.
|
||||
|
||||
One fun aspect of the [2024/endoh1/prog.c source code](%%REPO_URL%%/2024/endoh1/prog.c)
|
||||
is that when it is compiled an executed, the program outputs C code.
|
||||
That C code, call it `rt.c` will fail to compile! But that is OK because the C-preprocessor
|
||||
has enough work to do without bothering the C compiler. :-)
|
||||
|
||||
We plan to recognise those who report that they [rendered a new record sized image](endoh1/index.html#larger).
|
||||
|
||||
* [2024/weaver](weaver/index.html)
|
||||
|
||||
As the expression goes, “Seeing (and hearing) is believing”: or at least can lead to better understanding of the code. :o)
|
||||
|
||||
After studying the [2024/weaver/prog.c source code](%%REPO_URL%%/2024/weaver/prog.c),
|
||||
we suggest you compile and run the program for more information.
|
||||
|
||||
* [2024/mills](mills/index.html)
|
||||
|
||||
This won the "**Prize in ℤ₃**", but what does that mean? Well,
|
||||
the "_double-struck Z_" is **NOT** a reference to a set of integers,
|
||||
nor is the "_double-struck Z subscript 3_" a reference to a ring of
|
||||
3-adic integers. Instead, it is a reference to the 3rd version of a
|
||||
certain [virtual machine](https://en.wikipedia.org/wiki/Z-machine).
|
||||
|
||||
If you use the [2024/mills/try.sh](%%REPO_URL%%/2024/mills/try.sh) script, you will first be given
|
||||
an opportunity to view the [2024/mills/prog.c source code](%%REPO_URL%%/2024/mills/prog.c).
|
||||
Then you will be given 10 choices to play.
|
||||
|
||||
**HINT**: If you select **0**: Try to not be eaten by a Grue when
|
||||
reading/navigating the twisty mazes of this source code! :-)
|
||||
|
||||
* [2024/codemeow](codemeow/index.html)
|
||||
|
||||
As you study the [2024/codemeow/prog.c source code](%%REPO_URL%%/2024/codemeow/prog.c),
|
||||
try not to lose track of the forest of obfuscation while tracking down the execution path trees.
|
||||
|
||||
We think this code will "grow on you" as the C expression goes just a compiled C code "_grows on parse trees_". :-)
|
||||
|
||||
* [2024/kurdyukov2](kurdyukov2/index.html)
|
||||
|
||||
If seeing is believing, and you believe you understand the
|
||||
[2024/kurdyukov2/prog.c source code](%%REPO_URL%%/2024/kurdyukov2/prog.c),
|
||||
then you might be able to see how the code words.
|
||||
|
||||
**QUESTION**: How many of the "_magic numbers_" in the program do you understand?
|
||||
|
||||
* [2024/kurdyukov3](kurdyukov3/index.html)
|
||||
|
||||
The prize, "**virtual quietus**", is a virtual reference to the doom that awaits you when
|
||||
you run this code: let alone when your try to figure out how the author was able to
|
||||
encode the virtual machine in under **2.5K bytes** of [prog.c source code](%%REPO_URL%%/2024/kurdyukov3/prog.c)!
|
||||
|
||||
**NOTE**: The implementation runs without sound or mouse
|
||||
input. You will need reply on your keyboard skills. The
|
||||
[2024/kurdyukov3/try.sh](%%REPO_URL%%/2024/kurdyukov3/try.sh)
|
||||
demonstration script will give you some useful keyboard hints.
|
||||
|
||||
* [2024/cable2](cable2/index.html)
|
||||
|
||||
To those who follow the concept of "_seeing is believing_" will very
|
||||
likely be "_deceived_" when they try to see the source in terminal window:
|
||||
|
||||
``` <!---sh-->
|
||||
cat 2024/cable2/prog.c
|
||||
```
|
||||
|
||||
Viewing the [prog.c source code](%%REPO_URL%%/2024/cable2/prog.c) in most editors
|
||||
might suggest that the is something fishy 🐠 with the code.
|
||||
|
||||
* [2024/straadt](straadt/index.html)
|
||||
|
||||
Have you ever wondered would what would happen if you recursively removed
|
||||
files starting from the root directory? Are you curious what happens when
|
||||
you launch a [fork bomb](https://en.wikipedia.org/wiki/Fork_bomb)?
|
||||
You can safely give those and other scenarios under this virtual machine.
|
||||
|
||||
We invite you to explore the [prog.c source code](%%REPO_URL%%/2024/straadt/prog.c)
|
||||
to explore this interesting virtual machine implementation. And as a bonus, a
|
||||
full-fledged C64 emulator is included!
|
||||
|
||||
* [2024/ferguson2](ferguson2/index.html)
|
||||
|
||||
The "**Prize in yil-tas**" provides a hint as to what this marvelous
|
||||
winning entry is going, provided that you are someone familiar in at
|
||||
least 3 languages (**hint**: One of them is C, another id English).
|
||||
|
||||
The IOCCC is honored to present this entry for your enjoyment and you ponder
|
||||
the [prog.c source code](%%REPO_URL%%/2024/ferguson2/prog.c).
|
||||
|
||||
* [2024/carlini](carlini/index.html)
|
||||
|
||||
The IOCCC has seen a number of winning entries that allow code designed to
|
||||
run on early Intel processors, however none of them emulate a processor as
|
||||
early as the [Intel 4004](https://en.wikipedia.org/wiki/Intel_4004).
|
||||
Launched in 1971, the 4004 was the core of the first commercially marketed
|
||||
microprocessor chipset.
|
||||
|
||||
The [2024/carlini/prog.c](%%REPO_URL%%/2024/carlini/prog.c)
|
||||
code runs rather slow, so patience is required to watch
|
||||
[4004](https://en.wikipedia.org/wiki/Intel_4004#/media/File:Intel_C4004.jpg)
|
||||
code run. This is very understandable when you realize that the
|
||||
[2024/carlini/prog.c](%%REPO_URL%%/2024/carlini/prog.c) is actually
|
||||
emulating the entire
|
||||
[4004 chip circuit](https://en.wikipedia.org/wiki/Intel_4004#/media/File:Chip_layout_from_the_development_phase_of_the_Intel_4004_from_1971,_the_first_microprocessor_of_the_world_(cropped_and_edited_image).jpg)
|
||||
by computing the output of each gate in a loop, effectively running the CPU and associated RAM/ROM chips!
|
||||
|
||||
|
||||
### Remarks on some of submissions that did not win
|
||||
|
||||
* Depending on the address of a variable, as not all platforms support
|
||||
[ASLR](https://en.wikipedia.org/wiki/Address_space_layout_randomization),
|
||||
as the single source of pseudo-randomness isn’t a good idea. It’s
|
||||
much better to mix in other sources of variability (e.g. time, process
|
||||
ID, etc.) so that subsequent runs will behave differently.
|
||||
|
||||
* If a submission's obfuscation strongly resembles a past IOCCC winning
|
||||
entry, and the submission's obfuscation is mainly in the C code source,
|
||||
then the submission likely to not make it into the final rounds of judging.
|
||||
|
||||
* When working with modern C compilers, it’s crucial to explicitly
|
||||
declare variable and function types. Don’t assume they’ll
|
||||
automatically default to an `int`.
|
||||
|
||||
* Sadly, K&C-style C code does not compile well under modern C compilers.
|
||||
|
||||
* A submission that only works under gcc or clang does not work as well
|
||||
as submissions that can work under either compiler.
|
||||
|
||||
* Shrinking an existing open-source program to meet rule 2 size might
|
||||
be an impressive feat of code shrinking, but it might not be enough to
|
||||
make it into the final rounds of judging. Originality is key, and this
|
||||
might not be the most innovative approach.
|
||||
|
||||
* If your submission relies on mathematical algorithms, be sure that the
|
||||
C code that implements the mathematics is well obfuscated.
|
||||
|
||||
* Just a friendly reminder that before you upload your submissions,
|
||||
uncompress the compressed tarball into a different directory. This way,
|
||||
you can be sure you didn’t miss uploading any important files!
|
||||
|
||||
* Using a lot of goto statements to make your code harder to understand
|
||||
might not help it pass the final rounds of judging.
|
||||
|
||||
|
||||
### Encouragement for those who did not win this year
|
||||
|
||||
We know many of you that submitted to the IOCCC put in a ton of effort
|
||||
into your submissions for this year’s IOCCC. We can’t just give out
|
||||
awards to everyone. That would mean taking away from the submissions
|
||||
that we think are the best and deserve to win.
|
||||
|
||||
Sometimes, a final round submission might be good enough to be a
|
||||
winning IOCCC entry, only to be beaten by a similar, but slightly better
|
||||
submission. If you think this happened with your submission, consider
|
||||
submitting an enhanced version to the next IOCCC.
|
||||
|
||||
**PLEASE DO NOT** give up hope! There are some submissions that have been
|
||||
submitted with revisions, multiple times before rising to the level of
|
||||
a winning IOCCC entry. You might also want to try with a different type
|
||||
of submission altogether for the next IOCCC.
|
||||
|
||||
If you’re not planning to improve and resubmit your non-winning entry
|
||||
for the next IOCCC, you’re welcome to publish it.
|
||||
|
||||
|
||||
## On Compiling and running winning entries
|
||||
|
||||
Some C compilers aren’t as great as they could be. If yours isn’t
|
||||
working well, you might want to try compiling with an updated version
|
||||
of clang and/or gcc instead.
|
||||
|
||||
If you encounter problems in compiling and/or running the winning entries, see the FAQ on:
|
||||
|
||||
* [Compiling IOCCC entries](../faq.html#compiling)
|
||||
* [IOCCC entry dependencies](../faq.html#dependencies)
|
||||
* [Problems compiling entries](../faq.html#compile_problems)
|
||||
* [Running IOCCC entries](../faq.html#running_entries)
|
||||
|
||||
For additional information on how to submit fixes, see the FAQ on:
|
||||
|
||||
* [How to submit a fix](../faq.html#fix_an_entry) - how to submit a fix to an entry
|
||||
* [Update author information](../faq.html#fix_author) - how to correct or update an IOCCC author’s information
|
||||
|
||||
|
||||
### For even more information
|
||||
|
||||
* [Reporting an IOCCC website problem](../faq.html#report_website_problem)
|
||||
* [Submitting a fix to the IOCCC website](../faq.html#fix_website)
|
||||
* [How to contact the IOCCC](../contact.html) - up to date contact details
|
||||
* [IOCCC FAQ](../faq.html) - additional information on the IOCCC
|
||||
* [www.ioccc.org](https://www.ioccc.org) - the primary IOCCC website
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
Copyright © 1984-2025 by Landon Curt Noll and Leonid A. Broukhis. All Rights Reserved.
|
||||
|
||||
You are free to share and adapt this file under the terms of this license:
|
||||
|
||||
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
||||
|
||||
For more information, see:
|
||||
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
-->
|
||||
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"no_comment" : "mandatory comment: because comments were removed from the original JSON spec",
|
||||
"entry_JSON_format_version" : "1.2 2024-09-25",
|
||||
"award" : "Prize in sound coding",
|
||||
"year" : 2024,
|
||||
"dir" : "anders",
|
||||
"entry_id" : "2024_anders",
|
||||
"title" : "aks",
|
||||
"abstract" : "layered music generator",
|
||||
"author_set" : [
|
||||
{
|
||||
"author_handle" : "Anders_Kaare_Straadt"
|
||||
}
|
||||
],
|
||||
"manifest" : [
|
||||
{
|
||||
"file_path" : "prog.c",
|
||||
"inventory_order" : 20,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "c",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "entry source code"
|
||||
},
|
||||
{
|
||||
"file_path" : "Makefile",
|
||||
"inventory_order" : 30,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "makefile",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "entry Makefile"
|
||||
},
|
||||
{
|
||||
"file_path" : "prog.orig.c",
|
||||
"inventory_order" : 50,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "c",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "original source code"
|
||||
},
|
||||
{
|
||||
"file_path" : "try.sh",
|
||||
"inventory_order" : 100,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "script to try entry"
|
||||
},
|
||||
{
|
||||
"file_path" : "2024_anders.tar.bz2",
|
||||
"inventory_order" : 1415926535,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "tbz2",
|
||||
"display_via_github" : false,
|
||||
"entry_text" : "download entry tarball"
|
||||
},
|
||||
{
|
||||
"file_path" : ".entry.json",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "json",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "entry summary and manifest in JSON"
|
||||
},
|
||||
{
|
||||
"file_path" : ".gitignore",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "gitignore",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "list of files that should not be committed under git"
|
||||
},
|
||||
{
|
||||
"file_path" : ".path",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "path",
|
||||
"display_via_github" : false,
|
||||
"entry_text" : "directory path from top level directory"
|
||||
},
|
||||
{
|
||||
"file_path" : "README.md",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "markdown",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "markdown source for this web page"
|
||||
},
|
||||
{
|
||||
"file_path" : "index.html",
|
||||
"inventory_order" : 4294967295,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "html",
|
||||
"display_via_github" : false,
|
||||
"entry_text" : "this web page"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
prog.wav
|
||||
@@ -0,0 +1 @@
|
||||
2024/anders
|
||||
Binary file not shown.
@@ -0,0 +1,216 @@
|
||||
#!/usr/bin/env make
|
||||
#
|
||||
# 2024/anders
|
||||
|
||||
#############################
|
||||
# shell used by this Makefile
|
||||
#############################
|
||||
|
||||
SHELL= bash
|
||||
|
||||
|
||||
#######################
|
||||
# common tool locations
|
||||
#######################
|
||||
|
||||
include ../../var.mk
|
||||
|
||||
|
||||
#####################
|
||||
# C compiler settings
|
||||
#####################
|
||||
|
||||
# Common C compiler warnings to silence
|
||||
#
|
||||
# NOTE: Please don't add -Wno-unknown-warning-option to CSILENCE
|
||||
# (or to CUNKNOWN)
|
||||
#
|
||||
# NOTE: The author says this about -Wno-unsafe-buffer-usage
|
||||
#
|
||||
# # nah i'm not really into rust
|
||||
#
|
||||
CSILENCE= -Wno-int-in-bool-context -Wno-out-of-line-declaration \
|
||||
-Wno-unsafe-buffer-usage
|
||||
|
||||
# Attempt to silence unknown warning options
|
||||
#
|
||||
CUNKNOWN=
|
||||
|
||||
# Common C compiler warning flags
|
||||
#
|
||||
# NOTE: The addition of -pedantic to CWARN is a challenge that
|
||||
# You may wish to avoid if it proves too problematic.
|
||||
# There is NO penalty for removing -pedantic from CWARN.
|
||||
#
|
||||
CWARN= -Wall -Wextra -pedantic ${CSILENCE} ${CUNKNOWN}
|
||||
|
||||
# Compiler standard
|
||||
#
|
||||
CSTD= -std=gnu17
|
||||
|
||||
# Compiler bit architecture
|
||||
#
|
||||
# Example for 32-bitness: ARCH= -m32
|
||||
# Example for 64-bitness: ARCH= -m64
|
||||
#
|
||||
# NOTE: Normally one should NOT specify a specific architecture.
|
||||
#
|
||||
ARCH=
|
||||
|
||||
# Defines that are needed to compile
|
||||
#
|
||||
# Example: -Dfoo -Dbar=baz
|
||||
#
|
||||
CDEFINE=
|
||||
|
||||
# Include files that are needed to compile
|
||||
#
|
||||
# Example: CINCLUDE= -include stdio.h
|
||||
#
|
||||
CINCLUDE=
|
||||
|
||||
# Other flags to pass to the C compiler
|
||||
#
|
||||
# Example: COTHER= -fno-math-errno
|
||||
#
|
||||
COTHER=
|
||||
|
||||
# Optimization
|
||||
#
|
||||
# NOTE: Feel free to change the level of compiler optimization.
|
||||
# The "-O3" is just a friendly default you might wish to try.
|
||||
#
|
||||
# Example: OPT= -O0 -g
|
||||
#
|
||||
OPT= -O3
|
||||
|
||||
# Default flags for ANSI C compilation
|
||||
#
|
||||
CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${COTHER} ${OPT}
|
||||
|
||||
# Libraries needed to build
|
||||
#
|
||||
# Example: LDFLAGS= -lncurses -lm
|
||||
#
|
||||
LDFLAGS= -lm
|
||||
|
||||
# C compiler to use
|
||||
#
|
||||
# NOTE: The IOCCC Judges recommend you leave CC as just "cc"
|
||||
# and NOT set it to clang, or gcc, or something else
|
||||
# unless you have a STRONG reason to do so.
|
||||
#
|
||||
# Setting CC to something other than "cc" makes your
|
||||
# code less portable to those who do not have your
|
||||
# particular C compiler. **hint**
|
||||
#
|
||||
# If you want to test your code with a particular C compiler,
|
||||
# use the make command line. For example:
|
||||
#
|
||||
# make all CC=clang
|
||||
# make all CC=gcc
|
||||
#
|
||||
CC= cc
|
||||
|
||||
# Compiler add-ons or replacements for clang only
|
||||
#
|
||||
ifeq "$(findstring $(CLANG),${CC})" "$(CLANG)"
|
||||
#
|
||||
# NOTE: This code is only invoked when CC is "clang"
|
||||
# such as when you use the make command line:
|
||||
#
|
||||
# make all CC=clang
|
||||
#
|
||||
CSILENCE+= -Wno-poison-system-directories -Wno-unknown-warning-option
|
||||
#
|
||||
CWARN+= -Weverything
|
||||
#
|
||||
endif
|
||||
|
||||
# Specific add-ons or replacements for gcc only
|
||||
#
|
||||
ifeq "$(findstring $(GCC),${CC})" "$(GCC)"
|
||||
#
|
||||
# NOTE: This code is only invoked when CC is "gcc"
|
||||
# such as when you use the make command line:
|
||||
#
|
||||
# make all CC=gcc
|
||||
#
|
||||
CSILENCE+=
|
||||
#
|
||||
CWARN+=
|
||||
#
|
||||
endif
|
||||
|
||||
|
||||
###########################################
|
||||
# Special Makefile variables for this entry
|
||||
###########################################
|
||||
|
||||
ENTRY= prog
|
||||
PROG= ${ENTRY}
|
||||
#
|
||||
OBJ= ${PROG}.o
|
||||
TARGET= ${PROG}
|
||||
#
|
||||
ALT_OBJ=
|
||||
ALT_TARGET=
|
||||
|
||||
# list any data files supplied with your submission
|
||||
#
|
||||
# Example: DATA= curds whey
|
||||
#
|
||||
DATA=
|
||||
|
||||
|
||||
#################
|
||||
# build the entry
|
||||
#################
|
||||
|
||||
all: data ${TARGET}
|
||||
@${TRUE}
|
||||
|
||||
.PHONY: all alt data everything clean clobber
|
||||
|
||||
# how to compile
|
||||
#
|
||||
${PROG}: ${PROG}.c
|
||||
${CC} ${CFLAGS} ${PROG}.c -o $@ ${LDFLAGS}
|
||||
|
||||
# alternative executable
|
||||
#
|
||||
alt: data ${ALT_TARGET}
|
||||
@${TRUE}
|
||||
|
||||
${PROG}.alt: ${PROG}.alt.c
|
||||
${CC} ${CFLAGS} ${PROG}.alt.c -o $@ ${LDFLAGS}
|
||||
|
||||
# data files
|
||||
#
|
||||
data: ${DATA}
|
||||
@${TRUE}
|
||||
|
||||
# both all and alt
|
||||
#
|
||||
everything: all alt
|
||||
@${TRUE}
|
||||
|
||||
|
||||
###############
|
||||
# utility rules
|
||||
###############
|
||||
#
|
||||
clean:
|
||||
${RM} -f ${OBJ} ${ALT_OBJ}
|
||||
|
||||
clobber: clean
|
||||
${RM} -f ${TARGET} ${ALT_TARGET}
|
||||
${RM} -rf *.dSYM
|
||||
${RM} -f prog.wav
|
||||
|
||||
|
||||
######################################
|
||||
# optional include of 1337 hacker rulz
|
||||
######################################
|
||||
|
||||
-include 1337.mk ../1337.mk ../../1337.mk
|
||||
@@ -0,0 +1,93 @@
|
||||
## To build:
|
||||
|
||||
``` <!---sh-->
|
||||
make all
|
||||
```
|
||||
|
||||
|
||||
## To use:
|
||||
|
||||
``` <!---sh-->
|
||||
./prog
|
||||
```
|
||||
|
||||
|
||||
## Try:
|
||||
|
||||
``` <!---sh-->
|
||||
./prog
|
||||
```
|
||||
|
||||
and then play the resulting `prog.wav` using a sound player.
|
||||
|
||||
|
||||
## Judges' remarks:
|
||||
|
||||
When you run the program, after several moments, a `prog.wav` sound file is produced.
|
||||
|
||||
Using a sound player (you may find `sox(1)` is a good choice), you may enjoy the result.
|
||||
|
||||
Can you figure out how it produces the various layers of instruments?
|
||||
|
||||
|
||||
## Author's remarks:
|
||||
|
||||
|
||||
### Obfuscations
|
||||
|
||||
- "Helpful" formatting
|
||||
- Character salad
|
||||
- Loop exit trying to hide by a switch statement
|
||||
- Strong string encryption. By that I mean "fmt"=>"gnu".
|
||||
- A `/*{*/` that throws off bracket matching in vim. Begun the editor wars
|
||||
have! (Wait, I'm **on** the vim-team!)
|
||||
- `cm` and `ap` stands for "allpass" and "comb", respectively.
|
||||
- One effect was created with deliberate "memory corruption".
|
||||
|
||||
To encourage tinkering I've obfuscated the song data and program (see Y()) less
|
||||
than the "library code". Sorry if you wanted to tinker with the library code!
|
||||
|
||||
### Sound quality
|
||||
|
||||
The sample rate of prog.wav is 256kHz because creating aliasing-free waveforms
|
||||
would require more code, but you can always oversample the audio and pass the
|
||||
anti-aliasing problem on to the audio player :-) However, the downsampler in my
|
||||
`mplayer(1)` is poor, but you can use the high-quality resampler in `sox(1)` to create a
|
||||
48kHz version:
|
||||
|
||||
``` <!---c--->
|
||||
sox prog.wav -r 48000 prog.48kHz.wav
|
||||
```
|
||||
|
||||
### Tricks (the condescending part)
|
||||
|
||||
- Kick drum from sines, pitched up to create toms.
|
||||
- Roland TR-808 style hi-hats (a bunch of high-pass filtered square waves).
|
||||
- SID/C64-style snare drum (oscillates between noise and square wave).
|
||||
- There's some FM synthesis in the bass.
|
||||
- Schroeder reverberator a la Freeverb. The same building blocks are used for
|
||||
the echo effect.
|
||||
- Waveshaping/overdrive using tanh(x), ohh yeaaah..
|
||||
|
||||
I used this Python snippet to generate `q0[2]` and `q0[3]`:
|
||||
|
||||
``` <!---python-->
|
||||
def X(s): print(hex(int(s.replace("x","1").replace(".","0")[::-1],2))) # not for iopcc-use
|
||||
X(".x.x..xx.x.xx.xxx.xx.xxx..xx.xxx")
|
||||
X("x.xx.x.x.x.xxxxxx.xx.xxx.xxxxxxx")
|
||||
```
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
Copyright © 1984-2025 by Landon Curt Noll and Leonid A. Broukhis. All Rights Reserved.
|
||||
|
||||
You are free to share and adapt this file under the terms of this license:
|
||||
|
||||
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
||||
|
||||
For more information, see:
|
||||
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
-->
|
||||
@@ -0,0 +1,638 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<!-- START: two lines up starts content from: inc/top.default.html -->
|
||||
|
||||
<!-- END: this line ends content from: inc/top.default.html -->
|
||||
<!-- START: this line starts content from: inc/head.default.html -->
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../ioccc.css">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@100..900&display=swap" rel="stylesheet">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
<title>2024/anders - Prize in sound coding</title>
|
||||
<link rel="icon" type="image/x-icon" href="../../favicon.ico">
|
||||
<meta name="description" content="2024 IOCCC entry anders - Prize in sound coding">
|
||||
<meta name="keywords" content="IOCCC, 2024, IOCCC 2024, IOCCC entry, anders, Prize in sound coding">
|
||||
</head>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
|
||||
<!-- END: this line ends content from: inc/head.default.html -->
|
||||
|
||||
<!-- -->
|
||||
<!-- This web page was formed via the tool: bin/readme2index.sh -->
|
||||
<!-- The content of main section of this web page came from: 2024/anders/README.md -->
|
||||
<!-- -->
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<!-- !!! Do not modify this web page, instead modify the file: 2024/anders/README.md !!! -->
|
||||
<!-- !!! Do not modify this web page, instead modify the file: 2024/anders/README.md !!! -->
|
||||
<!-- !!! Do not modify this web page, instead modify the file: 2024/anders/README.md !!! -->
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
|
||||
<!-- Markdown content was converted into HTML via the tool: bin/md2html.sh -->
|
||||
|
||||
<!-- START: this line starts content from: inc/body.default.html -->
|
||||
|
||||
<body>
|
||||
|
||||
<!-- END: this line ends content from: inc/body.default.html -->
|
||||
<!-- START: this line starts content from: inc/topbar.default.html -->
|
||||
|
||||
<div class="theader">
|
||||
<nav class="topbar">
|
||||
<div class="container">
|
||||
<div class="logo">
|
||||
<a href="../../index.html" class="logo-link">
|
||||
IOCCC
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="topbar-items">
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
Entries
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../years.html" class="sub-item-link">
|
||||
Winning entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../authors.html" class="sub-item-link">
|
||||
Winning authors
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../location.html" class="sub-item-link">
|
||||
Location of authors
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../bugs.html" class="sub-item-link">
|
||||
Bugs and (mis)features
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#fix_an_entry" class="sub-item-link">
|
||||
Fixing entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#fix_author" class="sub-item-link">
|
||||
Updating author info
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
Status
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../news.html" class="sub-item-link">
|
||||
News
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../status.html" class="sub-item-link">
|
||||
Contest status
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../next/rules.html" class="sub-item-link">
|
||||
IOCCC rules
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../next/guidelines.html" class="sub-item-link">
|
||||
IOCCC guidelines
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../markdown.html" class="sub-item-link">
|
||||
Markdown guidelines
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../SECURITY.html" class="sub-item-link">
|
||||
Security policy
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
FAQ
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html" class="sub-item-link">
|
||||
Frequently asked questions
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../quick-start.html#enter" class="sub-item-link">
|
||||
Enter the IOCCC
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#compiling" class="sub-item-link">
|
||||
Compiling entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#running_entries" class="sub-item-link">
|
||||
Running entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#help" class="sub-item-link">
|
||||
How to help
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
About
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../index.html" class="sub-item-link">
|
||||
Home page
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../social.html" class="sub-item-link">
|
||||
IOCCC social media
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../about.html" class="sub-item-link">
|
||||
About the IOCCC
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../judges.html" class="sub-item-link">
|
||||
The judges
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../thanks-for-help.html" class="sub-item-link">
|
||||
Thanks for the help
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../contact.html" class="sub-item-link">
|
||||
Contact us
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="header-mobile-menu">
|
||||
<noscript>
|
||||
<a href="../../nojs-menu.html" class="topbar-js-label">
|
||||
Please Enable JavaScript
|
||||
</a>
|
||||
</noscript>
|
||||
|
||||
<button id="header-open-menu-button" class="topbar-mobile-menu">
|
||||
<img
|
||||
src="../../png/hamburger-icon-open.png"
|
||||
alt="hamburger style menu icon - open state"
|
||||
width=48
|
||||
height=48>
|
||||
</button>
|
||||
|
||||
<button id="header-close-menu-button" class="hide-content">
|
||||
<img
|
||||
src="../../png/hamburger-icon-closed.png"
|
||||
alt="hamburger style menu icon - closed state"
|
||||
width=48
|
||||
height=48>
|
||||
</button>
|
||||
|
||||
<div id="mobile-menu-panel" class="hide-content">
|
||||
<div class="mobile-menu-container">
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
<div class="mobile-menu-item">
|
||||
Entries
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../years.html">
|
||||
Winning entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../authors.html">
|
||||
Winning authors
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../location.html">
|
||||
Location of authors
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../bugs.html">
|
||||
Bugs and (mis)features
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#fix_an_entry">
|
||||
Fixing entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#fix_author">
|
||||
Updating author info
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../thanks-for-help.html">
|
||||
Thanks for the help
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
|
||||
<div class="mobile-menu-item">
|
||||
Status
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../news.html">
|
||||
News
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../status.html">
|
||||
Contest status
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../next/rules.html">
|
||||
IOCCC rules
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../next/guidelines.html">
|
||||
IOCCC guidelines
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../markdown.html">
|
||||
Markdown guidelines
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../SECURITY.html">
|
||||
Security policy
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
<div class="mobile-menu-item">
|
||||
FAQ
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html">
|
||||
Frequently asked questions
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../quick-start.html#enter">
|
||||
Enter the IOCCC
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#compiling">
|
||||
Compiling entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#running_entries">
|
||||
Running entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#help">
|
||||
How to help
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
<div class="mobile-menu-item">
|
||||
About
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../index.html">
|
||||
Home page
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../social.html">
|
||||
IOCCC social media
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../about.html">
|
||||
About the IOCCC
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../judges.html">
|
||||
The judges
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../contact.html">
|
||||
Contact us
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var headerOpenMenuButton = document.getElementById("header-open-menu-button");
|
||||
var headerCloseMenuButton = document.getElementById("header-close-menu-button");
|
||||
var mobileMenuPanel = document.getElementById("mobile-menu-panel");
|
||||
|
||||
headerOpenMenuButton.addEventListener("click", () => {
|
||||
headerOpenMenuButton.classList.remove("topbar-mobile-menu");
|
||||
headerOpenMenuButton.classList.add("hide-content");
|
||||
|
||||
headerCloseMenuButton.classList.remove("hide-content");
|
||||
headerCloseMenuButton.classList.add("topbar-mobile-menu");
|
||||
|
||||
mobileMenuPanel.classList.remove("hide-content");
|
||||
mobileMenuPanel.classList.add("topbar-mobile-panel");
|
||||
});
|
||||
|
||||
headerCloseMenuButton.addEventListener("click", () => {
|
||||
headerCloseMenuButton.classList.remove("topbar-mobile-menu");
|
||||
headerCloseMenuButton.classList.add("hide-content");
|
||||
|
||||
mobileMenuPanel.classList.add("hide-content");
|
||||
mobileMenuPanel.classList.remove("topbar-mobile-panel");
|
||||
|
||||
headerOpenMenuButton.classList.add("topbar-mobile-menu");
|
||||
headerOpenMenuButton.classList.remove("hide-content");
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- END: this line ends content from: inc/topbar.default.html -->
|
||||
<!-- START: this line starts content from: inc/header.default.html -->
|
||||
|
||||
<div class="header">
|
||||
<a href="../../2011/zucker/index.html">
|
||||
<img src="../../png/ioccc.png"
|
||||
alt="IOCCC image by Matt Zucker"
|
||||
width=300
|
||||
height=110>
|
||||
</a>
|
||||
<h1>The International Obfuscated C Code Contest</h1>
|
||||
<h2>2024/anders - Prize in sound coding</h2>
|
||||
<h3>layered music generator</h3>
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/header.default.html -->
|
||||
<!-- START: this line starts content from: inc/navbar.mid.html -->
|
||||
|
||||
<div class="navbar">
|
||||
<a class="Left" href="../../2020/yang/index.html">← 2020/yang</a>
|
||||
<a class="Left" href="../index.html">↑ 2024 ↑</a>
|
||||
<a class="Left" href="../burton/index.html">2024/burton →</a>
|
||||
<a class="Right" href="https://github.com/ioccc-src/winner/blob/master/2024/anders/prog.c">C code</a>
|
||||
<a class="Right" href="https://github.com/ioccc-src/winner/blob/master/2024/anders/Makefile">Makefile</a>
|
||||
<a class="Right" href="#inventory">Inventory</a>
|
||||
<a class="Right" href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fwww.ioccc.org%2F2024%2Fanders%2Findex.html">✓</a>
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/navbar.mid.html -->
|
||||
<!-- START: this line starts content from: inc/before-content.default.html -->
|
||||
|
||||
<div class="content" id="content">
|
||||
|
||||
<!-- END: this line ends content from: inc/before-content.default.html -->
|
||||
<!-- START: this line starts content for HTML phase 20 by: bin/output-index-author.sh via bin/md2html.sh -->
|
||||
|
||||
<!-- START: this line starts content generated by: bin/output-index-author.sh -->
|
||||
|
||||
<h2 id="author">Author:</h2>
|
||||
<ul>
|
||||
<li>Name: <a href="../../authors.html#Anders_Kaare_Straadt">Anders Kaare Straadt</a><br>
|
||||
Location: <a href="../../location.html#DK">DK</a> - <em>Denmark</em></li>
|
||||
</ul>
|
||||
|
||||
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
|
||||
|
||||
<!-- END: this line ends content for HTML phase 20 by: bin/output-index-author.sh via bin/md2html.sh -->
|
||||
<!-- START: this line starts content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||||
|
||||
<!-- BEFORE: 1st line of markdown file: 2024/anders/README.md -->
|
||||
<h2 id="to-build">To build:</h2>
|
||||
<pre><code> make all</code></pre>
|
||||
<h2 id="to-use">To use:</h2>
|
||||
<pre><code> ./prog</code></pre>
|
||||
<h2 id="try">Try:</h2>
|
||||
<pre><code> ./prog</code></pre>
|
||||
<p>and then play the resulting <code>prog.wav</code> using a sound player.</p>
|
||||
<h2 id="judges-remarks">Judges’ remarks:</h2>
|
||||
<p>When you run the program, after several moments, a <code>prog.wav</code> sound file is produced.</p>
|
||||
<p>Using a sound player (you may find <code>sox(1)</code> is a good choice), you may enjoy the result.</p>
|
||||
<p>Can you figure out how it produces the various layers of instruments?</p>
|
||||
<h2 id="authors-remarks">Author’s remarks:</h2>
|
||||
<h3 id="obfuscations">Obfuscations</h3>
|
||||
<ul>
|
||||
<li>“Helpful” formatting</li>
|
||||
<li>Character salad</li>
|
||||
<li>Loop exit trying to hide by a switch statement</li>
|
||||
<li>Strong string encryption. By that I mean “fmt”=>“gnu”.</li>
|
||||
<li>A <code>/*{*/</code> that throws off bracket matching in vim. Begun the editor wars
|
||||
have! (Wait, I’m <strong>on</strong> the vim-team!)</li>
|
||||
<li><code>cm</code> and <code>ap</code> stands for “allpass” and “comb”, respectively.</li>
|
||||
<li>One effect was created with deliberate “memory corruption”.</li>
|
||||
</ul>
|
||||
<p>To encourage tinkering I’ve obfuscated the song data and program (see Y()) less
|
||||
than the “library code”. Sorry if you wanted to tinker with the library code!</p>
|
||||
<h3 id="sound-quality">Sound quality</h3>
|
||||
<p>The sample rate of prog.wav is 256kHz because creating aliasing-free waveforms
|
||||
would require more code, but you can always oversample the audio and pass the
|
||||
anti-aliasing problem on to the audio player :-) However, the downsampler in my
|
||||
<code>mplayer(1)</code> is poor, but you can use the high-quality resampler in <code>sox(1)</code> to create a
|
||||
48kHz version:</p>
|
||||
<pre class="<!---c--->"><code> sox prog.wav -r 48000 prog.48kHz.wav</code></pre>
|
||||
<h3 id="tricks-the-condescending-part">Tricks (the condescending part)</h3>
|
||||
<ul>
|
||||
<li>Kick drum from sines, pitched up to create toms.</li>
|
||||
<li>Roland TR-808 style hi-hats (a bunch of high-pass filtered square waves).</li>
|
||||
<li>SID/C64-style snare drum (oscillates between noise and square wave).</li>
|
||||
<li>There’s some FM synthesis in the bass.</li>
|
||||
<li>Schroeder reverberator a la Freeverb. The same building blocks are used for
|
||||
the echo effect.</li>
|
||||
<li>Waveshaping/overdrive using tanh(x), ohh yeaaah..</li>
|
||||
</ul>
|
||||
<p>I used this Python snippet to generate <code>q0[2]</code> and <code>q0[3]</code>:</p>
|
||||
<pre><code> def X(s): print(hex(int(s.replace("x","1").replace(".","0")[::-1],2))) # not for iopcc-use
|
||||
X(".x.x..xx.x.xx.xxx.xx.xxx..xx.xxx")
|
||||
X("x.xx.x.x.x.xxxxxx.xx.xxx.xxxxxxx")</code></pre>
|
||||
<!--
|
||||
|
||||
Copyright © 1984-2025 by Landon Curt Noll and Leonid A. Broukhis. All Rights Reserved.
|
||||
|
||||
You are free to share and adapt this file under the terms of this license:
|
||||
|
||||
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
||||
|
||||
For more information, see:
|
||||
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
-->
|
||||
<!-- AFTER: last line of markdown file: 2024/anders/README.md -->
|
||||
|
||||
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||||
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
|
||||
|
||||
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
|
||||
|
||||
<div id="inventory">
|
||||
<h1 id="inventory-for-2024anders">Inventory for 2024/anders</h1>
|
||||
</div>
|
||||
<h2 id="primary-files">Primary files</h2>
|
||||
<ul>
|
||||
<li><a href="https://github.com/ioccc-src/winner/blob/master/2024/anders/prog.c">prog.c</a> - entry source code</li>
|
||||
<li><a href="https://github.com/ioccc-src/winner/blob/master/2024/anders/Makefile">Makefile</a> - entry Makefile</li>
|
||||
<li><a href="https://github.com/ioccc-src/winner/blob/master/2024/anders/prog.orig.c">prog.orig.c</a> - original source code</li>
|
||||
<li><a href="https://github.com/ioccc-src/winner/blob/master/2024/anders/try.sh">try.sh</a> - script to try entry</li>
|
||||
</ul>
|
||||
<h2 id="secondary-files">Secondary files</h2>
|
||||
<ul>
|
||||
<li><a href="2024_anders.tar.bz2">2024_anders.tar.bz2</a> - download entry tarball</li>
|
||||
<li><a href="https://github.com/ioccc-src/winner/blob/master/2024/anders/README.md">README.md</a> - markdown source for this web page</li>
|
||||
<li><a href="https://github.com/ioccc-src/winner/blob/master/2024/anders/.entry.json">.entry.json</a> - entry summary and manifest in JSON</li>
|
||||
<li><a href="https://github.com/ioccc-src/winner/blob/master/2024/anders/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
|
||||
<li><a href=".path">.path</a> - directory path from top level directory</li>
|
||||
<li><a href="index.html">index.html</a> - this web page</li>
|
||||
</ul>
|
||||
<hr style="width:10%;text-align:left;margin-left:0">
|
||||
<h4>
|
||||
Jump to: <a href="#">top</a>
|
||||
</h4>
|
||||
|
||||
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
|
||||
|
||||
<!-- END: this line ends content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
|
||||
<!-- START: this line starts content from: inc/after-content.default.html -->
|
||||
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/after-content.default.html -->
|
||||
<!-- START: this line starts content from: inc/footer.inventory.html -->
|
||||
|
||||
<!--
|
||||
|
||||
Copyright © 1984-2025 by Landon Curt Noll. All Rights Reserved.
|
||||
|
||||
You are free to share and adapt this file under the terms of this license:
|
||||
|
||||
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
||||
|
||||
For more information, see:
|
||||
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
-->
|
||||
|
||||
<div class="footer">
|
||||
|
||||
<div id="copyright"><h3>Copyright © 1984-2025 by Landon Curt Noll:
|
||||
<a href="https://creativecommons.org/faq/#what-does-some-rights-reserved-mean"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer">Some Rights Reserved</a></h3>
|
||||
<p>
|
||||
This work is <b>licensed by Landon Curt Noll</b> under
|
||||
<b><a href="https://creativecommons.org/licenses/by-sa/4.0/?ref=chooser-v1"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer"
|
||||
style="display:inline-block;">CC BY-SA 4.0</a></b>.
|
||||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||||
src="../../png/cc.png"
|
||||
alt="cc inside circle symbol">
|
||||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||||
src="../../png/by.png"
|
||||
alt="person inside circle symbol">
|
||||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||||
src="../../png/sa.png"
|
||||
alt="arrow looping back on itself inside circle symbol"><br>
|
||||
You should <b>carefully review</b> the
|
||||
<b><a href="https://creativecommons.org/licenses/by-sa/4.0/legalcode.en"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer">CC BY-SA 4.0 LEGAL CODE</a></b>
|
||||
before using the licensed material.<br>
|
||||
You may wish to review the
|
||||
<b><a href="../../license.html"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer">highlights of some of the key features and terms</a></b>
|
||||
of <b>CC BY-SA 4.0</b>.<br>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="coda"><h3>Coda</h3>
|
||||
<p>
|
||||
<a href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fwww.ioccc.org%2F2024%2Fanders%2Findex.html" rel="nofollow">Nu HTML check this web page</a><br>
|
||||
<a href="#top">Jump to top</a> <a href="#content">Jump to Content</a> <a href="#inventory">Jump to Inventory</a><br>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/footer.inventory.html -->
|
||||
<!-- START: this line starts content from: inc/bottom.default.html -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<!-- END: this line ends content from: inc/bottom.default.html -->
|
||||
@@ -0,0 +1,237 @@
|
||||
double static F=
|
||||
1.5e-3
|
||||
,t,b,D[1<<20],*E,U[4],X;
|
||||
|
||||
int static B=
|
||||
17e3
|
||||
,J,I,N;
|
||||
|
||||
unsigned static q0[]={
|
||||
0x0ce97522,
|
||||
0xc02972e5,
|
||||
0xeceddaca,
|
||||
0xfeedfaad,
|
||||
};
|
||||
|
||||
int static q1[]={
|
||||
-2, 0, 7,
|
||||
0, 3, 10,
|
||||
|
||||
-5, 0, 0, 2, 3, 0, 2, 2,
|
||||
-2, 0, 7, 12, 3, 7, 5, 10,
|
||||
|
||||
0, 3, -5,
|
||||
-2, 7, 3,
|
||||
-2, 2, -5,
|
||||
-10,-2, 5
|
||||
}
|
||||
|
||||
; char static*q2[]={
|
||||
"XBWFgnu!" ,
|
||||
"ebub","SJGG" ,
|
||||
"\njust a moment.."
|
||||
} ,*P,M[1<<29]
|
||||
|
||||
#define S sin
|
||||
#define O pow
|
||||
#define H tanh
|
||||
#define C(b)double*j=G(n+2),o; int c=(int)j[n+1]; b; if(++c>=n)c=0; j[n+1]=c; return o;
|
||||
#define A(n)for(j=0; j<n; ++j)
|
||||
; int static T( int x ) { return I/(B<<x) ; }
|
||||
double static dp( int a,int c ){ return (double)((I+B*c)%(B<<a)) /(B<<a); }
|
||||
void static L(short w){ *P++=( char ) w; *P++=w>>3 >>5; }
|
||||
double static Q( int a ) { return dp (a,0); }
|
||||
void static Z(char*s ) { for ( char*q=s; *q; ++q, ++P) *P=*q -1; }
|
||||
double static qb( int p ) { return I%p<p>>2 ?1:-1; }
|
||||
double static* G( int n ) { E+=n; return E -n; }
|
||||
void static W( int l ) { L( ( short )l); L((short)(l>>13 >>3) )
|
||||
; }
|
||||
#include <math.h>
|
||||
#include<stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void static Y(double p, double g, double e, double r)
|
||||
{
|
||||
U[2] += e * X ;
|
||||
U[0] += X * p * fmin(1,1-g) ;
|
||||
U[3] += r * X ;
|
||||
U[1] += fmin(g+1,1) * X * p ;
|
||||
}
|
||||
|
||||
double static eq(double x,double a,double h,double c,double d,double e)
|
||||
{
|
||||
double *z=
|
||||
G(2) , y=a*x+
|
||||
z[0] ;
|
||||
z[0] = x*h-d*y+
|
||||
z[1] ;
|
||||
z[1] = c*x-y*e;
|
||||
return y;
|
||||
}
|
||||
|
||||
double static ap(double x,int n,double f,double d) { C (
|
||||
o=
|
||||
j[c] ;
|
||||
j[n] =o* (1-d)+
|
||||
j[n] *d;
|
||||
j[c] =x+
|
||||
j[n] *f
|
||||
;
|
||||
)
|
||||
} double static cm
|
||||
( double x,int n,double
|
||||
f )
|
||||
{ C
|
||||
( double u=
|
||||
j [c ]; o=u-x;
|
||||
j[c ] =f*u+x; )
|
||||
} int
|
||||
main
|
||||
( void )
|
||||
{ int j ,
|
||||
k , l , m ;
|
||||
char * px = P
|
||||
= M
|
||||
,
|
||||
* pa ,
|
||||
*
|
||||
p0 ; FILE
|
||||
* o ;
|
||||
|
||||
|
||||
|
||||
N=(B*5)<<8;
|
||||
|
||||
|
||||
|
||||
Z ( q2 [ 2 ] ) ; W
|
||||
( 36 + ( N << 2 ) ) ;
|
||||
Z ( q2 [ 0 ] )
|
||||
; W ( 16 ) ;
|
||||
L ( 1 ) ; L ( 2
|
||||
) ; W ( 1 << 18
|
||||
) ; W ( 4 << 18
|
||||
) ; L ( 4 ) ;L
|
||||
( 16 ) ; Z ( q2
|
||||
[1 ] ) ; W(N <<
|
||||
2) ; for( pa = P ; ;
|
||||
) { E= D ; A ( 4 )
|
||||
U [ j ] = 0 ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
l=((T(3)+32)%64)-61;
|
||||
t=H(Q((l<0?3:l)));
|
||||
X=H(50*S(t*141+t*(15e3/(4+t*330)))*O(1-H(t),9));
|
||||
if (T(10)) X=0;
|
||||
Y(.5,0,.07,.1);
|
||||
|
||||
|
||||
X=0;
|
||||
A(8) X+=qb(211+(j*113+T(2)*91)%1291);
|
||||
X=eq(X,.973,-1.946,.973,-1.942,.951);
|
||||
X=H(X*2);
|
||||
l=T(4)%8>6;
|
||||
switch (T(8)) {
|
||||
case 0 : t=H(Q((T(4))%4)); break;
|
||||
case 2 : t=H(Q(2-l)); break;
|
||||
default : case 1 : t=H(Q(1-l)); break;
|
||||
} if (++I>N) break;
|
||||
X*=O(1-t,4)*O(Q(3),2);
|
||||
X=H(X*1.4);
|
||||
if (!(T(7)&7) || T(10)) X=0;
|
||||
Y(.8,S(I*1e-5),.16,.4);
|
||||
|
||||
|
||||
t=1-(((T(2)&63)>61)?H(Q(1))/6:H(dp(4,8)));
|
||||
X=I&(1<<12)?(double)(rand())/RAND_MAX-.5:.1*qb(1400-(int)(t*301));
|
||||
X=H(30*X*O(t,40));
|
||||
if (!(T(7)&3) || T(10)) X=0;
|
||||
Y(.8,.3,1,.3);
|
||||
|
||||
l=T(6)%4;
|
||||
k=(q0[l>2]>>((T(3)&7)<<2))&15;
|
||||
b=F*I*O(2,(double)k/12);
|
||||
k=T(8)%2;
|
||||
m=((q0[2+l%2])>>(T(1)&31))&1;
|
||||
X=m?S(b+1.5*S(I*7e-5)+S(I*3e-7)*(4+3*S(I*1.7e-7))*S(b*(1+k))):0;
|
||||
if (T(8)) X+=((S(b*.501)>.95)-(S(b*.498)>.8))*15*O(Q(3),2);
|
||||
t=1-H(Q(1));
|
||||
X=H(25*X*O(t,3));
|
||||
if (T(10)) X=0;
|
||||
Y(.4,0,.12,.02);
|
||||
|
||||
|
||||
A(3) {
|
||||
k=T(1)%32+3;
|
||||
k-=k/4*3;
|
||||
l=T(6)&1;
|
||||
k=l ? 24+q1[6 + T(7)%2*8 + T(3)%8] : T(9) ? 24+q1[22+(k+j)%3+T(4)%4*3] : q1[k%3+T(7)%2*3] + (k/3)*12;
|
||||
X=F*I*O(2,((double)(14+k)+(j-1)*.4)/12)+S(j+I*(l?1e-4:3e-4))*(l?4:1);
|
||||
t=S(X)+.3*(fmod(X,6.3)-3);
|
||||
X=t+.3*(t>.9*S(I*6.3e-7)?1:-1);
|
||||
t=1-H(Q(l?2:m?2:1));
|
||||
X=H(X*O(t,9)*(T(10)?O(1-Q(8),3):1));
|
||||
if (T(6)%2*!T(9) || !T(8)) X=0;
|
||||
Y( 1,S(2*j+I*3e-6),.3,.3);
|
||||
}
|
||||
|
||||
X=ap(U[3],(int)(B*6.1),.2,.2);
|
||||
Y(1,-.6,.1,0);
|
||||
X=cm(U[3],(int)(B*3.8),.2);
|
||||
Y(.7,.6,.1,0);
|
||||
|
||||
|
||||
for (k=0; k<2; ++k) {
|
||||
X=0;
|
||||
A(8) X+=ap(U[2],4001+(j*2131+k*1555)%3491,.8,.5);
|
||||
A(4) X=cm(X,800+((j+T(8))*1337+k*1441)%1303,.4);
|
||||
X=H(X/4);
|
||||
Y( .3,k?-1:1,0,0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A(
|
||||
2)
|
||||
L (
|
||||
( short)
|
||||
(fmin (1
|
||||
,fmax (-1,
|
||||
U [
|
||||
j ]
|
||||
) ) *32e3
|
||||
) ); if ( !
|
||||
( I %(
|
||||
B * 8) ) )
|
||||
{ putchar (q2
|
||||
[3 ]
|
||||
/*{*/[
|
||||
++J&15 ] ) ;
|
||||
fflush ( stdout ) ;
|
||||
} } pa=P ;
|
||||
Z("opx!fokpz!" ); p0=P ;
|
||||
Z("qsph/xbw" );
|
||||
o=fopen(p0,"wb") ; fwrite(
|
||||
px, 1, (
|
||||
|
||||
unsigned
|
||||
long )( pa-px),o); fclose(
|
||||
o); puts ( pa ) ; return(
|
||||
|
||||
signed
|
||||
)0; }
|
||||
@@ -0,0 +1,237 @@
|
||||
double static F=
|
||||
1.5e-3
|
||||
,t,b,D[1<<20],*E,U[4],X;
|
||||
|
||||
int static B=
|
||||
17e3
|
||||
,J,I,N;
|
||||
|
||||
unsigned static q0[]={
|
||||
0x0ce97522,
|
||||
0xc02972e5,
|
||||
0xeceddaca,
|
||||
0xfeedfaad,
|
||||
};
|
||||
|
||||
int static q1[]={
|
||||
-2, 0, 7,
|
||||
0, 3, 10,
|
||||
|
||||
-5, 0, 0, 2, 3, 0, 2, 2,
|
||||
-2, 0, 7, 12, 3, 7, 5, 10,
|
||||
|
||||
0, 3, -5,
|
||||
-2, 7, 3,
|
||||
-2, 2, -5,
|
||||
-10,-2, 5
|
||||
}
|
||||
|
||||
; char static*q2[]={
|
||||
"XBWFgnu!" ,
|
||||
"ebub","SJGG" ,
|
||||
"\njust a moment.."
|
||||
} ,*P,M[1<<29]
|
||||
|
||||
#define S sin
|
||||
#define O pow
|
||||
#define H tanh
|
||||
#define C(b)double*j=G(n+2),o; int c=(int)j[n+1]; b; if(++c>=n)c=0; j[n+1]=c; return o;
|
||||
#define A(n)for(j=0; j<n; ++j)
|
||||
; int static T( int x ) { return I/(B<<x) ; }
|
||||
double static dp( int a,int c ){ return (double)((I+B*c)%(B<<a)) /(B<<a); }
|
||||
void static L(short w){ *P++=( char ) w; *P++=w>>3 >>5; }
|
||||
double static Q( int a ) { return dp (a,0); }
|
||||
void static Z(char*s ) { for ( char*q=s; *q; ++q, ++P) *P=*q -1; }
|
||||
double static qb( int p ) { return I%p<p>>2 ?1:-1; }
|
||||
double static* G( int n ) { E+=n; return E -n; }
|
||||
void static W( int l ) { L( ( short )l); L((short)(l>>13 >>3) )
|
||||
; }
|
||||
#include <math.h>
|
||||
#include<stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void static Y(double p, double g, double e, double r)
|
||||
{
|
||||
U[2] += e * X ;
|
||||
U[0] += X * p * fmin(1,1-g) ;
|
||||
U[3] += r * X ;
|
||||
U[1] += fmin(g+1,1) * X * p ;
|
||||
}
|
||||
|
||||
double static eq(double x,double a,double h,double c,double d,double e)
|
||||
{
|
||||
double *z=
|
||||
G(2) , y=a*x+
|
||||
z[0] ;
|
||||
z[0] = x*h-d*y+
|
||||
z[1] ;
|
||||
z[1] = c*x-y*e;
|
||||
return y;
|
||||
}
|
||||
|
||||
double static ap(double x,int n,double f,double d) { C (
|
||||
o=
|
||||
j[c] ;
|
||||
j[n] =o* (1-d)+
|
||||
j[n] *d;
|
||||
j[c] =x+
|
||||
j[n] *f
|
||||
;
|
||||
)
|
||||
} double static cm
|
||||
( double x,int n,double
|
||||
f )
|
||||
{ C
|
||||
( double u=
|
||||
j [c ]; o=u-x;
|
||||
j[c ] =f*u+x; )
|
||||
} int
|
||||
main
|
||||
( void )
|
||||
{ int j ,
|
||||
k , l , m ;
|
||||
char * px = P
|
||||
= M
|
||||
,
|
||||
* pa ,
|
||||
*
|
||||
p0 ; FILE
|
||||
* o ;
|
||||
|
||||
|
||||
|
||||
N=(B*5)<<8;
|
||||
|
||||
|
||||
|
||||
Z ( q2 [ 2 ] ) ; W
|
||||
( 36 + ( N << 2 ) ) ;
|
||||
Z ( q2 [ 0 ] )
|
||||
; W ( 16 ) ;
|
||||
L ( 1 ) ; L ( 2
|
||||
) ; W ( 1 << 18
|
||||
) ; W ( 4 << 18
|
||||
) ; L ( 4 ) ;L
|
||||
( 16 ) ; Z ( q2
|
||||
[1 ] ) ; W(N <<
|
||||
2) ; for( pa = P ; ;
|
||||
) { E= D ; A ( 4 )
|
||||
U [ j ] = 0 ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
l=((T(3)+32)%64)-61;
|
||||
t=H(Q((l<0?3:l)));
|
||||
X=H(50*S(t*141+t*(15e3/(4+t*330)))*O(1-H(t),9));
|
||||
if (T(10)) X=0;
|
||||
Y(.5,0,.07,.1);
|
||||
|
||||
|
||||
X=0;
|
||||
A(8) X+=qb(211+(j*113+T(2)*91)%1291);
|
||||
X=eq(X,.973,-1.946,.973,-1.942,.951);
|
||||
X=H(X*2);
|
||||
l=T(4)%8>6;
|
||||
switch (T(8)) {
|
||||
case 0 : t=H(Q((T(4))%4)); break;
|
||||
case 2 : t=H(Q(2-l)); break;
|
||||
default : case 1 : t=H(Q(1-l)); break;
|
||||
} if (++I>N) break;
|
||||
X*=O(1-t,4)*O(Q(3),2);
|
||||
X=H(X*1.4);
|
||||
if (!(T(7)&7) || T(10)) X=0;
|
||||
Y(.8,S(I*1e-5),.16,.4);
|
||||
|
||||
|
||||
t=1-(((T(2)&63)>61)?H(Q(1))/6:H(dp(4,8)));
|
||||
X=I&(1<<12)?(double)(rand())/RAND_MAX-.5:.1*qb(1400-(int)(t*301));
|
||||
X=H(30*X*O(t,40));
|
||||
if (!(T(7)&3) || T(10)) X=0;
|
||||
Y(.8,.3,1,.3);
|
||||
|
||||
l=T(6)%4;
|
||||
k=(q0[l>2]>>((T(3)&7)<<2))&15;
|
||||
b=F*I*O(2,(double)k/12);
|
||||
k=T(8)%2;
|
||||
m=((q0[2+l%2])>>(T(1)&31))&1;
|
||||
X=m?S(b+1.5*S(I*7e-5)+S(I*3e-7)*(4+3*S(I*1.7e-7))*S(b*(1+k))):0;
|
||||
if (T(8)) X+=((S(b*.501)>.95)-(S(b*.498)>.8))*15*O(Q(3),2);
|
||||
t=1-H(Q(1));
|
||||
X=H(25*X*O(t,3));
|
||||
if (T(10)) X=0;
|
||||
Y(.4,0,.12,.02);
|
||||
|
||||
|
||||
A(3) {
|
||||
k=T(1)%32+3;
|
||||
k-=k/4*3;
|
||||
l=T(6)&1;
|
||||
k=l ? 24+q1[6 + T(7)%2*8 + T(3)%8] : T(9) ? 24+q1[22+(k+j)%3+T(4)%4*3] : q1[k%3+T(7)%2*3] + (k/3)*12;
|
||||
X=F*I*O(2,((double)(14+k)+(j-1)*.4)/12)+S(j+I*(l?1e-4:3e-4))*(l?4:1);
|
||||
t=S(X)+.3*(fmod(X,6.3)-3);
|
||||
X=t+.3*(t>.9*S(I*6.3e-7)?1:-1);
|
||||
t=1-H(Q(l?2:m?2:1));
|
||||
X=H(X*O(t,9)*(T(10)?O(1-Q(8),3):1));
|
||||
if (T(6)%2*!T(9) || !T(8)) X=0;
|
||||
Y( 1,S(2*j+I*3e-6),.3,.3);
|
||||
}
|
||||
|
||||
X=ap(U[3],(int)(B*6.1),.2,.2);
|
||||
Y(1,-.6,.1,0);
|
||||
X=cm(U[3],(int)(B*3.8),.2);
|
||||
Y(.7,.6,.1,0);
|
||||
|
||||
|
||||
for (k=0; k<2; ++k) {
|
||||
X=0;
|
||||
A(8) X+=ap(U[2],4001+(j*2131+k*1555)%3491,.8,.5);
|
||||
A(4) X=cm(X,800+((j+T(8))*1337+k*1441)%1303,.4);
|
||||
X=H(X/4);
|
||||
Y( .3,k?-1:1,0,0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A(
|
||||
2)
|
||||
L (
|
||||
( short)
|
||||
(fmin (1
|
||||
,fmax (-1,
|
||||
U [
|
||||
j ]
|
||||
) ) *32e3
|
||||
) ); if ( !
|
||||
( I %(
|
||||
B * 8) ) )
|
||||
{ putchar (q2
|
||||
[3 ]
|
||||
/*{*/[
|
||||
++J&15 ] ) ;
|
||||
fflush ( stdout ) ;
|
||||
} } pa=P ;
|
||||
Z("opx!fokpz!" ); p0=P ;
|
||||
Z("qsph/xbw" );
|
||||
o=fopen(p0,"wb") ; fwrite(
|
||||
px, 1, (
|
||||
|
||||
unsigned
|
||||
long )( pa-px),o); fclose(
|
||||
o); puts ( pa ) ; return(
|
||||
|
||||
signed
|
||||
)0; }
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# try.sh - demonstrate 2024/anders
|
||||
|
||||
# make sure CC is set so that when we do make CC="$CC" it isn't empty. Doing it
|
||||
# this way allows us to have the user specify a different compiler in an easy way.
|
||||
#
|
||||
[[ -z "$CC" ]] && CC="cc"
|
||||
|
||||
# make sure the program has been built
|
||||
#
|
||||
make CC="$CC" all >/dev/null || exit 1
|
||||
|
||||
# clear the screen
|
||||
#
|
||||
clear
|
||||
|
||||
# try the program
|
||||
#
|
||||
read -r -n 1 -p "Press any key to run: ./prog: "
|
||||
echo 1>&2
|
||||
echo 1>&2
|
||||
./prog
|
||||
echo 1>&2
|
||||
@@ -0,0 +1,361 @@
|
||||
{
|
||||
"no_comment" : "mandatory comment: because comments were removed from the original JSON spec",
|
||||
"entry_JSON_format_version" : "1.2 2024-09-25",
|
||||
"award" : "Prize in pentagrammatology",
|
||||
"year" : 2024,
|
||||
"dir" : "burton",
|
||||
"entry_id" : "2024_burton",
|
||||
"title" : "wordle",
|
||||
"abstract" : "wordle hard mode solver",
|
||||
"author_set" : [
|
||||
{
|
||||
"author_handle" : "Dave_Burton"
|
||||
}
|
||||
],
|
||||
"manifest" : [
|
||||
{
|
||||
"file_path" : "prog.c",
|
||||
"inventory_order" : 20,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "c",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "entry source code"
|
||||
},
|
||||
{
|
||||
"file_path" : "Makefile",
|
||||
"inventory_order" : 30,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "makefile",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "entry Makefile"
|
||||
},
|
||||
{
|
||||
"file_path" : "prog.orig.c",
|
||||
"inventory_order" : 50,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "c",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "original source code"
|
||||
},
|
||||
{
|
||||
"file_path" : "deobfuscated.html",
|
||||
"inventory_order" : 100,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "markdown",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "about deobfuscation"
|
||||
},
|
||||
{
|
||||
"file_path" : "dict",
|
||||
"inventory_order" : 100,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "text",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "5-letter wordle dictionary"
|
||||
},
|
||||
{
|
||||
"file_path" : "extra.html",
|
||||
"inventory_order" : 100,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "markdown",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "description of the extra files"
|
||||
},
|
||||
{
|
||||
"file_path" : "reveal.c",
|
||||
"inventory_order" : 100,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "c",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "reveal wordle hints"
|
||||
},
|
||||
{
|
||||
"file_path" : "try.sh",
|
||||
"inventory_order" : 100,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "script to try entry"
|
||||
},
|
||||
{
|
||||
"file_path" : "deobfuscated.c",
|
||||
"inventory_order" : 150,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "c",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "deobfuscated source code"
|
||||
},
|
||||
{
|
||||
"file_path" : "gen.c",
|
||||
"inventory_order" : 150,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "c",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "simulate wordle games"
|
||||
},
|
||||
{
|
||||
"file_path" : "worst",
|
||||
"inventory_order" : 150,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "determine worst target words"
|
||||
},
|
||||
{
|
||||
"file_path" : "2024_01_18_wordle_stats.png",
|
||||
"inventory_order" : 200,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "image",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "wordle stats"
|
||||
},
|
||||
{
|
||||
"file_path" : "avg",
|
||||
"inventory_order" : 200,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "simple analysis script"
|
||||
},
|
||||
{
|
||||
"file_path" : "comp.avg",
|
||||
"inventory_order" : 200,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "compute averages"
|
||||
},
|
||||
{
|
||||
"file_path" : "dups.c",
|
||||
"inventory_order" : 200,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "c",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "remove repeated letters"
|
||||
},
|
||||
{
|
||||
"file_path" : "exhaust",
|
||||
"inventory_order" : 200,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "exhaustive test of all wordle words"
|
||||
},
|
||||
{
|
||||
"file_path" : "extra_guesses",
|
||||
"inventory_order" : 200,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "allow extra wordle guesses"
|
||||
},
|
||||
{
|
||||
"file_path" : "freq",
|
||||
"inventory_order" : 200,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "letter frequency in wordle words"
|
||||
},
|
||||
{
|
||||
"file_path" : "mkresults",
|
||||
"inventory_order" : 200,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "report showing average word accuracy"
|
||||
},
|
||||
{
|
||||
"file_path" : "rank",
|
||||
"inventory_order" : 200,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "how averages are calculated and missed words"
|
||||
},
|
||||
{
|
||||
"file_path" : "run.c",
|
||||
"inventory_order" : 200,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "c",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "automated testing tool"
|
||||
},
|
||||
{
|
||||
"file_path" : "unob.c",
|
||||
"inventory_order" : 200,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "c",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "unobfuscator tool source code"
|
||||
},
|
||||
{
|
||||
"file_path" : "wavg",
|
||||
"inventory_order" : 200,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "weigh six scores"
|
||||
},
|
||||
{
|
||||
"file_path" : "word.result",
|
||||
"inventory_order" : 200,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "produce results of a"
|
||||
},
|
||||
{
|
||||
"file_path" : "wrank",
|
||||
"inventory_order" : 200,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "weighted rank tool"
|
||||
},
|
||||
{
|
||||
"file_path" : "2024_burton.tar.bz2",
|
||||
"inventory_order" : 1415926535,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "tbz2",
|
||||
"display_via_github" : false,
|
||||
"entry_text" : "download entry tarball"
|
||||
},
|
||||
{
|
||||
"file_path" : ".entry.json",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "json",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "entry summary and manifest in JSON"
|
||||
},
|
||||
{
|
||||
"file_path" : ".gitignore",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "gitignore",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "list of files that should not be committed under git"
|
||||
},
|
||||
{
|
||||
"file_path" : ".path",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "path",
|
||||
"display_via_github" : false,
|
||||
"entry_text" : "directory path from top level directory"
|
||||
},
|
||||
{
|
||||
"file_path" : "README.md",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "markdown",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "markdown source for this web page"
|
||||
},
|
||||
{
|
||||
"file_path" : "correct.test.abode",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "text",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "correct test of the word abode"
|
||||
},
|
||||
{
|
||||
"file_path" : "correct.test.jaunt",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "text",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "correct test of the word jaunt"
|
||||
},
|
||||
{
|
||||
"file_path" : "correct.test.light",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "text",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "correct test of the word light"
|
||||
},
|
||||
{
|
||||
"file_path" : "deobfuscated.md",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "markdown",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "markdown source for deobfuscated.html"
|
||||
},
|
||||
{
|
||||
"file_path" : "extra.md",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "markdown",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "markdown source for extra.html"
|
||||
},
|
||||
{
|
||||
"file_path" : "r.blast",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "text",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "analysis for the word blast"
|
||||
},
|
||||
{
|
||||
"file_path" : "r.crate",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "text",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "analysis for the word crate"
|
||||
},
|
||||
{
|
||||
"file_path" : "r.query",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "text",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "analysis for the word query"
|
||||
},
|
||||
{
|
||||
"file_path" : "r.terns",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "text",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "analysis for the word terns"
|
||||
},
|
||||
{
|
||||
"file_path" : "test.abode",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "text",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "analysis for the word"
|
||||
},
|
||||
{
|
||||
"file_path" : "test.jaunt",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "text",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "analysis for the jaunt"
|
||||
},
|
||||
{
|
||||
"file_path" : "test.light",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "text",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "analysis for the word light"
|
||||
},
|
||||
{
|
||||
"file_path" : "index.html",
|
||||
"inventory_order" : 4294967295,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "html",
|
||||
"display_via_github" : false,
|
||||
"entry_text" : "this web page"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
dups
|
||||
fmt
|
||||
fmt.c
|
||||
gen
|
||||
reveal
|
||||
run
|
||||
usdw
|
||||
@@ -0,0 +1 @@
|
||||
2024/burton
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
Binary file not shown.
@@ -0,0 +1,269 @@
|
||||
#!/usr/bin/env make
|
||||
#
|
||||
# 2024/burton
|
||||
|
||||
#############################
|
||||
# shell used by this Makefile
|
||||
#############################
|
||||
|
||||
SHELL= bash
|
||||
|
||||
|
||||
#######################
|
||||
# common tool locations
|
||||
#######################
|
||||
|
||||
include ../../var.mk
|
||||
|
||||
|
||||
#####################
|
||||
# C compiler settings
|
||||
#####################
|
||||
|
||||
# Common C compiler warnings to silence
|
||||
#
|
||||
# Example: CSILENCE= -Wno-poison-system-directories
|
||||
#
|
||||
CSILENCE= -Wno-misleading-indentation -Wno-parentheses -Wno-unused-value
|
||||
|
||||
# Attempt to silence unknown warning options
|
||||
#
|
||||
CUNKNOWN= -Wno-unknown-warning-option
|
||||
|
||||
# Common C compiler warning flags
|
||||
#
|
||||
# NOTE: The addition of -pedantic to CWARN is a challenge that
|
||||
# You may wish to avoid if it proves too problematic.
|
||||
# There is NO penalty for removing -pedantic from CWARN.
|
||||
#
|
||||
CWARN= -Wall -Wextra -pedantic ${CSILENCE} ${CUNKNOWN}
|
||||
|
||||
# Compiler standard
|
||||
#
|
||||
CSTD= -std=gnu17
|
||||
|
||||
# Compiler bit architecture
|
||||
#
|
||||
# Example for 32-bitness: ARCH= -m32
|
||||
# Example for 64-bitness: ARCH= -m64
|
||||
#
|
||||
# NOTE: Normally one should NOT specify a specific architecture.
|
||||
#
|
||||
ARCH=
|
||||
|
||||
# Defines that are needed to compile
|
||||
#
|
||||
# Example: -Dfoo -Dbar=baz
|
||||
#
|
||||
CDEFINE= -D_FORTIFY_SOURCE=0
|
||||
|
||||
# Include files that are needed to compile
|
||||
#
|
||||
# Example: CINCLUDE= -include stdio.h
|
||||
#
|
||||
CINCLUDE=
|
||||
|
||||
# Other flags to pass to the C compiler
|
||||
#
|
||||
# Example: COTHER= -fno-math-errno
|
||||
#
|
||||
COTHER=
|
||||
|
||||
# Optimization
|
||||
#
|
||||
# NOTE: Feel free to change the level of compiler optimization.
|
||||
# The "-O3" is just a friendly default you might wish to try.
|
||||
#
|
||||
# Example: OPT= -O0 -g
|
||||
#
|
||||
OPT= -O3
|
||||
|
||||
# Default flags for ANSI C compilation
|
||||
#
|
||||
CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${COTHER} ${OPT}
|
||||
|
||||
# Libraries needed to build
|
||||
#
|
||||
# Example: LDFLAGS= -lncurses -lm
|
||||
#
|
||||
LDFLAGS=
|
||||
|
||||
# C compiler to use
|
||||
#
|
||||
# NOTE: The IOCCC Judges recommend you leave CC as just "cc"
|
||||
# and NOT set it to clang, or gcc, or something else
|
||||
# unless you have a STRONG reason to do so.
|
||||
#
|
||||
# Setting CC to something other than "cc" makes your
|
||||
# code less portable to those who do not have your
|
||||
# particular C compiler. **hint**
|
||||
#
|
||||
# If you want to test your code with a particular C compiler,
|
||||
# use the make command line. For example:
|
||||
#
|
||||
# make all CC=clang
|
||||
# make all CC=gcc
|
||||
#
|
||||
CC= cc
|
||||
|
||||
# Compiler add-ons or replacements for clang only
|
||||
#
|
||||
ifeq "$(findstring $(CLANG),${CC})" "$(CLANG)"
|
||||
#
|
||||
# NOTE: This code is only invoked when CC is "clang"
|
||||
# such as when you use the make command line:
|
||||
#
|
||||
# make all CC=clang
|
||||
#
|
||||
CSILENCE+= -Wno-array-bounds-pointer-arithmetic -Wno-comma \
|
||||
-Wno-declaration-after-statement -Wno-format-nonliteral \
|
||||
-Wno-implicit-int-conversion -Wno-missing-prototypes \
|
||||
-Wno-missing-variable-declarations -Wno-poison-system-directories \
|
||||
-Wno-shadow -Wno-shorten-64-to-32 -Wno-vla -Wno-extra-semi-stmt \
|
||||
-Wno-misleading-indentation -Wno-unsafe-buffer-usage
|
||||
#
|
||||
CWARN+= -Weverything
|
||||
#
|
||||
endif
|
||||
|
||||
# Specific add-ons or replacements for gcc only
|
||||
#
|
||||
ifeq "$(findstring $(GCC),${CC})" "$(GCC)"
|
||||
#
|
||||
# NOTE: This code is only invoked when CC is "gcc"
|
||||
# such as when you use the make command line:
|
||||
#
|
||||
# make all CC=gcc
|
||||
#
|
||||
CSILENCE+=
|
||||
#
|
||||
CWARN+=
|
||||
#
|
||||
endif
|
||||
|
||||
|
||||
###########################################
|
||||
# Special Makefile variables for this entry
|
||||
###########################################
|
||||
|
||||
ENTRY= prog
|
||||
PROG= ${ENTRY}
|
||||
#
|
||||
OBJ= ${PROG}.o
|
||||
TARGET= ${PROG} ${TOOLS}
|
||||
#
|
||||
ALT_OBJ=
|
||||
ALT_TARGET=
|
||||
|
||||
# list any data files supplied with your submission
|
||||
#
|
||||
# Example: DATA= curds whey
|
||||
#
|
||||
DATA= dict test.abode test.light test.jaunt correct.test.abode \
|
||||
correct.test.jaunt correct.test.light r.blast r.crate r.query r.terns
|
||||
|
||||
# utility scripts
|
||||
#
|
||||
SCRIPTS= avg comp.avg exhaust extra_guesses freq mkresults rank wavg word.result worst wrank
|
||||
TOOLS= gen dups run reveal usdw
|
||||
IOCCCSIZE= iocccsize
|
||||
DICTIONARY= /usr/share/dict/words
|
||||
|
||||
|
||||
#################
|
||||
# build the entry
|
||||
#################
|
||||
|
||||
all: data ${TARGET} ${SCRIPTS} ${TOOLS}
|
||||
@${TRUE}
|
||||
|
||||
.PHONY: all alt data everything clean clobber
|
||||
|
||||
# how to compile
|
||||
#
|
||||
${PROG}: ${PROG}.c
|
||||
${CC} ${CFLAGS} ${PROG}.c -o $@ ${LDFLAGS}
|
||||
|
||||
define stest
|
||||
echo -n "$(2): ";
|
||||
if ${CAT} $(2) | $(1) dict | ${DIFF} - correct.$(2); then echo pass; else echo fail; fi
|
||||
endef
|
||||
|
||||
test: prog size
|
||||
@ $(call stest,./prog,test.light,-lt)
|
||||
@ $(call stest,./prog,test.abode,-lt)
|
||||
@ $(call stest,./prog,test.jaunt,-eq)
|
||||
|
||||
size:
|
||||
${IOCCCSIZE} prog.c
|
||||
@# iocccsize-2019 -i < prog.c
|
||||
@# iocccsize-2020 -i < prog.c > /dev/null
|
||||
|
||||
tfmt: fmt
|
||||
@ $(call stest,./fmt,test.light,-lt)
|
||||
@ $(call stest,./fmt,test.abode,-lt)
|
||||
@ $(call stest,./fmt,test.jaunt,-eq)
|
||||
|
||||
fmt: fmt.c
|
||||
${CC} ${CFLAGS} fmt.c -o $@ ${LDFLAGS}
|
||||
|
||||
fmt.c: prog.c
|
||||
${RM} -f $@
|
||||
${CLANG_FORMAT} -style=file < prog.c > fmt.c
|
||||
|
||||
dups: dups.c
|
||||
${CC} ${CFLAGS} dups.c -o $@ ${LDFLAGS}
|
||||
|
||||
gen: gen.c
|
||||
${CC} ${CFLAGS} gen.c -o $@ ${LDFLAGS}
|
||||
|
||||
run: run.c
|
||||
${CC} ${CFLAGS} run.c -o $@ ${LDFLAGS}
|
||||
|
||||
reveal: reveal.c
|
||||
${CC} ${CFLAGS} reveal.c -o $@ ${LDFLAGS}
|
||||
|
||||
usdw:
|
||||
${RM} -f $@
|
||||
${GREP} '^.....$$' ${DICTIONARY} | ${GREP} -v '[A-Z]' | ${GREP} -v beant > $@
|
||||
|
||||
spoiler: reveal fmt.c
|
||||
@if test -x ${CLANG_FORMAT}; then ${CLANG_FORMAT} -style=file < prog.c | ./reveal; else ./reveal < fmt.c; fi
|
||||
|
||||
# alternative executable
|
||||
#
|
||||
alt: data ${ALT_TARGET}
|
||||
@${TRUE}
|
||||
|
||||
${PROG}.alt: ${PROG}.alt.c
|
||||
${CC} ${CFLAGS} ${PROG}.alt.c -o $@ ${LDFLAGS}
|
||||
|
||||
# data files
|
||||
#
|
||||
data: ${DATA}
|
||||
@${TRUE}
|
||||
|
||||
# both all and alt
|
||||
#
|
||||
everything: all alt
|
||||
@${TRUE}
|
||||
|
||||
|
||||
###############
|
||||
# utility rules
|
||||
###############
|
||||
#
|
||||
clean:
|
||||
${RM} -f ${OBJ} ${ALT_OBJ}
|
||||
|
||||
clobber: clean
|
||||
${RM} -f ${TARGET} ${ALT_TARGET}
|
||||
${RM} -rf *.dSYM
|
||||
${RM} -f fmt.c fmt
|
||||
|
||||
|
||||
######################################
|
||||
# optional include of 1337 hacker rulz
|
||||
######################################
|
||||
|
||||
-include 1337.mk ../1337.mk ../../1337.mk
|
||||
@@ -0,0 +1,546 @@
|
||||
## To build:
|
||||
|
||||
``` <!---sh-->
|
||||
make all
|
||||
```
|
||||
|
||||
|
||||
## To use:
|
||||
|
||||
``` <!---sh-->
|
||||
./prog dict
|
||||
```
|
||||
|
||||
|
||||
## Try:
|
||||
|
||||
``` <!---sh-->
|
||||
./try.sh
|
||||
```
|
||||
|
||||
|
||||
## Judges' remarks:
|
||||
|
||||
We were impressed with the algorithm, but one question remains: is there a
|
||||
strategy which reduces the probability of a loss even further, at the cost of
|
||||
requiring a higher average number of guesses?
|
||||
|
||||
|
||||
## Author's remarks:
|
||||
|
||||
This program is an assistant for solving hard-mode [Wordle(tm)][1]
|
||||
(you must use any revealed hints in all subsequent guesses)
|
||||
accurately/efficiently - in the fewest guesses.
|
||||
The program expects lower case input in two words: `guess color`,
|
||||
followed by newline.
|
||||
|
||||
- `guess` is the 5 letter word you guessed,
|
||||
- `color` is 5 letters from the set [g,y,b]
|
||||
|
||||
that correspond to the colors shown in Wordle: g=green, y=yellow, b=black.
|
||||
|
||||
[1]: https://www.nytimes.com/games/wordle/index.html
|
||||
|
||||
Start the program with a single argument, the name of a dictionary of words.
|
||||
`/usr/share/dict/words` is a perfectly cromulent dictionary,
|
||||
but the included file `dict` contains the 2315 target words from the original
|
||||
Wordle game and consistently provides the fewest guesses.
|
||||
|
||||
As an example session, Wordle 226 has the target word `light`.
|
||||
The recommended first guess (for all Wordle puzzles) is `blast`, `terns`,
|
||||
or `crate` (see the [extra.html](extra.html) that accompanies this entry for details).
|
||||
|
||||
Enter `terns` in game 226 of Wordle, and click the enter button.
|
||||
The letters will turn yellow, black, black, black, black.
|
||||
This assistant prompts "? ", and the input expected is the guessed word
|
||||
followed by the first letters of the color revealed for that guess:
|
||||
|
||||
``` <!---sh-->
|
||||
$ prog dict
|
||||
? terns ybbbb
|
||||
loath
|
||||
? loath gbbyy
|
||||
light
|
||||
$
|
||||
```
|
||||
|
||||
The program responds with the recommended next guess. Enter
|
||||
this word `loath` into the game, which then reveals the colors
|
||||
green, black, black, yellow, yellow. Typing `loath gbbyy` into
|
||||
this assistant shows the solution is `light`, and exits.
|
||||
Type this word into the game, click enter, and viola!
|
||||
Solved in 3 guesses: terns > loath > light.
|
||||
|
||||
This program averages better than 4 guesses on the 1566 starting words
|
||||
without duplicate letters created by `./dups -n < dict`,
|
||||
ranging from 3.587 to 3.997, with an overall average of 3.748 guesses.
|
||||
|
||||
This is excellent performance, and close to optimal.
|
||||
See this YouTube presentation on [solving Wordle using information theory][2],
|
||||
which shows a hard mode average of 3.562 when using `crane`
|
||||
(time offset 29:58). There is a small correction video changing
|
||||
[`crane` to `salet`, `trace` or `crate`][3].
|
||||
NB: These videos are NOT spoilers for this algorithm.
|
||||
|
||||
[2]: https://www.youtube.com/watch?v=v68zYyaEmEA
|
||||
[3]: https://www.youtube.com/watch?v=fRed0Xmc2Wg
|
||||
|
||||
`prog` does NOT require you to use its offered guess.
|
||||
If you think you have a better guess than offered,
|
||||
simply type your guess and the Wordle/`gen` responses into `prog`;
|
||||
it will internally re-adjust using your input instead of its guess,
|
||||
and produce what it thinks is the best next guess after your input.
|
||||
|
||||
|
||||
### A Feature
|
||||
|
||||
Caution: When there are duplicate letters in the guess word,
|
||||
and one of them is marked black and the other non-black,
|
||||
this program MUST have the black letter marked *yellow*.
|
||||
The example session (Wordle 228) below demonstrates this:
|
||||
|
||||
```
|
||||
# do NOT do this
|
||||
$ prog dict
|
||||
? terns bbbby
|
||||
shoal
|
||||
? shoal gggbb
|
||||
shook
|
||||
? shook gggbg <<-- this is what Wordle shows
|
||||
xyzzy <<-- no candidate words match
|
||||
|
||||
# do THIS instead
|
||||
$ prog dict
|
||||
? terns bbbby
|
||||
shoal
|
||||
? shoal gggbb
|
||||
shook
|
||||
? shook gggyg <<-- not gggbg as shown in the game
|
||||
shock
|
||||
? shock ggggg
|
||||
shock
|
||||
```
|
||||
|
||||
In the guess word `shook`, there are 2 o's, but only one shown valid in
|
||||
the puzzle. If you mark the leftmost o as black (as according to the
|
||||
Wordle game), this program cannot find the winning word (`shock`),
|
||||
producing the error word `xyzzy`.
|
||||
|
||||
The included simulator `gen` produces the required transformation of b -> y.
|
||||
|
||||
The extra program `run` connects `gen` and `prog`, allowing for quick tests.
|
||||
|
||||
```
|
||||
make tools
|
||||
./run dict terns shock # test starting guess `terns` against target `shock`
|
||||
```
|
||||
|
||||
Using `run` allows one to quickly and easily experiment with different
|
||||
starting words for different target words, seeing how the guesses progress.
|
||||
|
||||
(A late tweak to the program improved its accuracy, and in the above example,
|
||||
the progression is now terns > shoal > shock. However, the caution remains
|
||||
for any duplicate letter guesses.)
|
||||
|
||||
|
||||
### Failure mode
|
||||
|
||||
The following 4 words from the included file `dict` are not guessed correctly
|
||||
within 6 guesses when using the recommended (via exhaustive testing)
|
||||
starting guess of `blast`. Since this program is deterministic, these
|
||||
four words always require 7 guesses when starting with `blast`, yielding
|
||||
a failure rate of 4/2315, or a success rate of 99.8%.
|
||||
|
||||
```
|
||||
foyer jaunt shave wound
|
||||
```
|
||||
|
||||
Using the ancillary programs `run`, `exhaust`, and `mkresults`,
|
||||
the starting word `blast` yields the fewest misses at these four words,
|
||||
with an accuracy/efficiency of 3.67. See [extra.html](extra.html)
|
||||
for more detail.
|
||||
|
||||
This program also has a benefit the game Wordle does not:
|
||||
Wordle allows several thousand extra words to use in guesses not in `dict`.
|
||||
This program does not restrict _any_ words, so one could enter any
|
||||
combination of 5 letters as input, except these are unlikely to be accepted
|
||||
by the Wordle game, and this program selects its words from the much more
|
||||
limited set that is present in `dict`. Using an expanded dictionary like
|
||||
`/usr/share/dict/words` provides a richer set of guesses, but generally
|
||||
increases the average number of guesses and the failure rate.
|
||||
|
||||
|
||||
### Interesting questions
|
||||
|
||||
- How are candidate words chosen?
|
||||
- How does the array of numbers relate to finding a word?
|
||||
- It is interesting to see the final stages of picking a word.
|
||||
You might be interested to add observability? (Hint: `make tfmt`)
|
||||
Although `clang-format` is unlikely to help you understand the code,
|
||||
`printf`'s will help you understand how the "tables" are used:
|
||||
|
||||
"Show me your flowcharts and conceal your tables,
|
||||
and I shall continue to by mystified;
|
||||
show me your tables and I won't usually need your flowcharts...."
|
||||
-- Fred Brooks
|
||||
|
||||
- There is a plausible "tunable", not exposed. It selects when to
|
||||
discard certain words. What is this value, and how important is this
|
||||
value in optimizing results?
|
||||
- There is a debatable "bug" in the code, but it actually _improves_ the
|
||||
results. Where and why?
|
||||
Hint: the limit `for` a loop. ;-)
|
||||
- This solver/assistant is pretty interesting to play with, experiment with.
|
||||
Can you improve it?
|
||||
|
||||
|
||||
### Did you notice?
|
||||
|
||||
- Wordle is spelled in the code several different ways, one is obscure.
|
||||
If you need help, try this command (which requires `clang-format`):
|
||||
|
||||
```
|
||||
make spoiler
|
||||
```
|
||||
|
||||
- My second favorite language is spelled out thrice in the source code.
|
||||
- Variables are mostly generic a,b,c and i,j,k,l and reused in different
|
||||
scopes. Have fun!
|
||||
- The Sierpinski[4] number? What in the world is a Sierpinski number?
|
||||
|
||||
[4]: https://planetmath.org/sierpinskinumber
|
||||
|
||||
|
||||
### Time Passages (Apologies to Al Stewart)
|
||||
|
||||
This code was written in mid January 2022, before the NYT purchased Wordle[tm].
|
||||
|
||||
I have since used this assistant to play the game for more than a year,
|
||||
confirming my local experiments.
|
||||
|
||||

|
||||
|
||||
The dictionary changed in 2023! In late March 2023, I encountered the first
|
||||
word not in `dict`: `guano`. In a bit of a surprise, I tried:
|
||||
|
||||
```
|
||||
blast bbgbb
|
||||
reach bbgbb
|
||||
piano bbggg
|
||||
xyzzy
|
||||
```
|
||||
|
||||
What? The only word in `dict` ending in `ano` is `piano`. So I tried again
|
||||
using `/usr/share/dict/words`:
|
||||
|
||||
```
|
||||
blast bbgbb
|
||||
crane bbggb
|
||||
guano ggggg
|
||||
```
|
||||
|
||||
Blending the two, the puzzle was guessed in 4 tries total:
|
||||
|
||||
```
|
||||
blast > reach > piano > guano
|
||||
```
|
||||
|
||||
So caveat emptor: while `dict` used to be authoritative, we know some words
|
||||
were deemed offensive and removed. More problematic, some words were added,
|
||||
although I am presently unaware of which words. The existence proof is the
|
||||
above mentioned `guano`. There are almost certainly other words missing.
|
||||
|
||||
With `guano` added to `dict`, it is guessed in 3 using `blast` as the
|
||||
starting word:
|
||||
|
||||
```
|
||||
blast bbgbb
|
||||
reach bbgbb
|
||||
guano ggggg
|
||||
```
|
||||
|
||||
NB: `dict` has not been changed. `gauno` was NOT added to `dict`.
|
||||
Adding this word changes the statistics, and thus requires a change
|
||||
to all this material. It has a *slightly* negative impact, except
|
||||
for it finds the word `guano`. Essentially, as you add new words
|
||||
to `dict`, the permutations expand, and the scores decrease. This is
|
||||
why `/usr/share/dict/words` scores worse than `dict` - and loses more often.
|
||||
|
||||
April 9, 2023, this problem repeated with the target word `snafu`.
|
||||
That seems apropos.
|
||||
|
||||
```
|
||||
$ ./prog dict
|
||||
blast bbgyb
|
||||
share gbgbb
|
||||
spank gbgyb
|
||||
xyzzy
|
||||
|
||||
$ ./prog /usr/share/dict/words
|
||||
blast bbgyb
|
||||
share gbgbb
|
||||
spank gbgyb
|
||||
snafu ggggg
|
||||
```
|
||||
|
||||
And on June 9, 2023, again. This time, it cost nothing, and won on the
|
||||
second guess.
|
||||
|
||||
```
|
||||
$ ./prog dict
|
||||
blast gyygb
|
||||
xyzzy
|
||||
|
||||
$ ./prog /usr/share/dict/words
|
||||
blast gyygb
|
||||
balsa ggggg
|
||||
```
|
||||
|
||||
June 19, 2023, another one wasn't working, so time for a better dictionary:
|
||||
|
||||
```
|
||||
$ ./prog dict
|
||||
blast bbybb
|
||||
ramen bgbbb
|
||||
vapid bgbbb
|
||||
wacky bgbyb
|
||||
xyzzy
|
||||
|
||||
# a copy of /usr/share/dict/words with five letters and no capitals:
|
||||
grep '^.....$' /usr/share/dict/words | grep -v '[A-Z]' > ./usdw
|
||||
|
||||
$ ./prog usdw
|
||||
blast bbybb
|
||||
redan bbbyb
|
||||
campo bgbbg
|
||||
wahoo bgbgg
|
||||
kazoo ggggg
|
||||
```
|
||||
|
||||
As of June 19, 2023, it is known that at least these words have been added
|
||||
(more are likely). Using `./usdw` as above, `prog` guesses these words in:
|
||||
|
||||
```
|
||||
guano 3
|
||||
snafu 4
|
||||
balsa 2
|
||||
kazoo 5
|
||||
```
|
||||
|
||||
See the [extra.html](extra.html) for more details on the program `run`:
|
||||
|
||||
```
|
||||
for n in guano snafu balsa kazoo; do
|
||||
./run usdw blast $n;
|
||||
done | grep good
|
||||
```
|
||||
|
||||
As of April 22, 2024, add the word `laser` in 3 guesses.
|
||||
|
||||
```
|
||||
$ ./prog usdw
|
||||
blast byyyb
|
||||
solea ybygy
|
||||
laser ggggg
|
||||
```
|
||||
|
||||
And May 8, 2024 brings on `pious` in 4 guesses (after the failure with `dict`):
|
||||
|
||||
```
|
||||
$ prog dict
|
||||
blast bbbyb
|
||||
siren ygbbb
|
||||
ficus bgbgg
|
||||
xyzzy
|
||||
|
||||
$ prog usdw
|
||||
? blast bbbyb
|
||||
serio
|
||||
? siren ygbbb
|
||||
pisco
|
||||
? ficus bgbgg
|
||||
pious
|
||||
? pious ggggg
|
||||
```
|
||||
|
||||
Notice here that the suggested word was NOT used, instead the original
|
||||
guesses were used, and it found the correct answer in 4 guesses.
|
||||
However, doing
|
||||
|
||||
```
|
||||
./run usdw blast pious
|
||||
```
|
||||
|
||||
gets the answer correct in 3 guesses: blast > serio > pious.
|
||||
|
||||
And Sep 17, 2024 brings us the word `beaut`.
|
||||
|
||||
```
|
||||
$ prog dict
|
||||
blast gbgbg
|
||||
xyzzy
|
||||
|
||||
$ prog usdw
|
||||
blast gbgbgb
|
||||
beant -- not allowed, so removed beant from usdw
|
||||
brant gbgbg
|
||||
beaut ggggg
|
||||
```
|
||||
|
||||
Three guesses using an alternate dictionary and having to remove `beant`.
|
||||
This word isn't even a word I can find in Webster's. I hope your version
|
||||
of `/usr/share/dict/words` has more cromulent words.
|
||||
|
||||
Oct 9, 2024 brings the word `mommy`.
|
||||
|
||||
```
|
||||
$ prog dict
|
||||
blast bbbbb
|
||||
drone bbybb
|
||||
pouch bgbbb
|
||||
foggy bgbbg
|
||||
|
||||
$ prog usdw
|
||||
blast bbbbb
|
||||
drone bbybb
|
||||
pouch bgbbb
|
||||
foggy bgbbg
|
||||
mommy ggggg
|
||||
```
|
||||
|
||||
Fortunately, the program is good enough that failing with one
|
||||
dictionary still allows you to switch dictionaries and win.
|
||||
|
||||
Nov 13, 2024 brings `primp`.
|
||||
|
||||
```
|
||||
$ ./prog dict
|
||||
blast bbbbb
|
||||
drone bgbbb
|
||||
crimp bgggg
|
||||
xyzzy
|
||||
|
||||
$ ./prog usdw
|
||||
blast bbbbb
|
||||
drone bgbbb
|
||||
crimp bgggg
|
||||
primp ggggg
|
||||
```
|
||||
|
||||
Jan 20, 2025 brings the word `squid`.
|
||||
|
||||
```
|
||||
$ ./prog dict
|
||||
blast bbbyb
|
||||
siren gybbb
|
||||
skimp gbybb
|
||||
sushi <<-- last plausible word
|
||||
|
||||
$ ./prog usdw
|
||||
blast bbbyb
|
||||
siren gybbb
|
||||
skimp gbybb
|
||||
sushi sgbby
|
||||
squid ggggg
|
||||
```
|
||||
|
||||
As of Jan 20, 2025, the ten known words not in `dict` are
|
||||
(scores are using `usdw`, not `dict`, which lacks these words):
|
||||
|
||||
```
|
||||
guano 4
|
||||
snafu 5
|
||||
balsa 3
|
||||
kazoo 4
|
||||
laser 3
|
||||
pious 4
|
||||
beaut 3
|
||||
mommy 4
|
||||
primp 5
|
||||
squid 4
|
||||
```
|
||||
|
||||
Feb 18, 2025 adds a word not in `dict` nor `usdw`. "indie".
|
||||
|
||||
```
|
||||
$ ./prog dict
|
||||
blast bbbbb
|
||||
drone ybbyg
|
||||
undue bggbg
|
||||
xyzzy
|
||||
|
||||
$ ./prog usdw
|
||||
blast bbbbb
|
||||
drone ybbyg
|
||||
undue bggbg
|
||||
xyzzy
|
||||
|
||||
I grep'd the dictionaries. No plausbile hits.
|
||||
So I solved it the old fashioned way: I guessed.
|
||||
|
||||
blast bbbbb
|
||||
drone ybbyg
|
||||
undue bggbg
|
||||
indie ggggg
|
||||
|
||||
This solved it in 4, but the program could not win.
|
||||
So add to the summary list above:
|
||||
|
||||
indie 4
|
||||
```
|
||||
|
||||
|
||||
### Compilation
|
||||
|
||||
Compiles cleanly with `-Wall -Wpedantic -Wextra`,
|
||||
on MACOS M2 Clang/GCC 14 and Linux X86 Gcc 8.5.
|
||||
|
||||
If you are using `-Weverything`,
|
||||
which IMHO is exceptionally noisy about non-problems,
|
||||
and given the requirements of obfuscation and layout,
|
||||
there are a few `-Wno-` flags required to achieve a
|
||||
quiet compilation:
|
||||
|
||||
```
|
||||
-Wno-poison-system-directories \
|
||||
-Wno-missing-variable-declarations \
|
||||
-Wno-shadow \
|
||||
-Wno-vla \
|
||||
-Wno-missing-prototypes \
|
||||
-Wno-shorten-64-to-32 \
|
||||
-Wno-format-nonliteral \
|
||||
-Wno-implicit-int-conversion \
|
||||
-Wno-declaration-after-statement \
|
||||
-Wno-comma \
|
||||
-Wno-array-bounds-pointer-arithmetic \
|
||||
-Wno-sign-conversion
|
||||
```
|
||||
|
||||
The code uses variable length arrays, omitted the keyword `static`
|
||||
for functions and global variables, and collide `size_t` with `int`
|
||||
for return types. There are no pedantic prototypes for functions.
|
||||
There is no misuse of the comma operator, but try getting the compiler
|
||||
to ignore it. The code has been run on MacOS M2 and Linux x86 with
|
||||
no failures observed. And as documented in [deobfuscated.html](deobfuscated.html),
|
||||
pointer bounds are intentionally abused for obfuscation, but the
|
||||
code is correct as documented.
|
||||
This is obfuscated C, so yes, variables are intentionally shadowed.
|
||||
`printf()` is also abused, passing in non-literals as the format.
|
||||
|
||||
Perhaps there is some platform out there that won't work correctly
|
||||
due to the omissions noted above, but I am unaware of these.
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
Copyright © 1984-2025 by Landon Curt Noll and Leonid A. Broukhis. All Rights Reserved.
|
||||
|
||||
You are free to share and adapt this file under the terms of this license:
|
||||
|
||||
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
||||
|
||||
For more information, see:
|
||||
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
-->
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
awk '
|
||||
/^guess1/ {if (w == "") w = $2 }
|
||||
/good:/ {n++; t+=$5 }
|
||||
/lose:/ {n++; L++ }
|
||||
END {printf "%s %.06f %d\n",w,t/n,L }' $1
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
a=$1
|
||||
b=$2
|
||||
|
||||
if test $# -ne 2; then echo "usage: $0 result.a result.b" >&2; exit 1; fi
|
||||
|
||||
join $a $b | awk '
|
||||
{
|
||||
davg=$4-$2
|
||||
dloss=$5-$3
|
||||
print $0, davg, dloss
|
||||
}
|
||||
' | tabby
|
||||
@@ -0,0 +1,3 @@
|
||||
? amber
|
||||
? adobe
|
||||
? abode
|
||||
@@ -0,0 +1,6 @@
|
||||
? daunt
|
||||
? haunt
|
||||
? gaunt
|
||||
? vaunt
|
||||
? taunt
|
||||
? jaunt
|
||||
@@ -0,0 +1,2 @@
|
||||
? loath
|
||||
? light
|
||||
@@ -0,0 +1,165 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef void q;
|
||||
typedef int _;
|
||||
typedef char p;
|
||||
|
||||
struct {
|
||||
p a[257], b[9][5], c[5], d[5];
|
||||
_ e, f;
|
||||
} i;
|
||||
p t[78557][5];
|
||||
_ s, a[] = {
|
||||
9, 9, 9, 10, 13, 18, 27, 39, 55, 1, 18, 2, 1, 1,
|
||||
35, 2, 19, 18, 1, 52, 36, 35, 20, 3, 2, 19, 18, 18,
|
||||
69, 2, 53, 1, 52, 37, 3, 20, 36, 19, 35, 18, 52, 86,
|
||||
2, 53, 70, 1, 69, 38, /* 36 */ 4, 21, 3, 37, 19,
|
||||
36, 35, 25, 10, 17, 15, 26, 9, 11, 12, 23, 2, 6, 18,
|
||||
13, 20, 22, 14, 1, 24, 19, 21, 16, 5, 7, 4, 8, 3
|
||||
} , u = ' ';
|
||||
|
||||
_ W(p *a, p *b) {
|
||||
for (p *c = a + 5; a < c; )
|
||||
*a++ = *b++;
|
||||
return 0;
|
||||
}
|
||||
_ O(p *a, p b) {
|
||||
p *c = a + 5;
|
||||
for (; a < c && *a - b; )
|
||||
++a;
|
||||
return a < c ? 5 - (a - c) : 0;
|
||||
}
|
||||
_ R(p *a, ...) {
|
||||
va_list b;
|
||||
va_start(b, a);
|
||||
vprintf(a, b);
|
||||
exit(1);
|
||||
}
|
||||
q D(p *a) {
|
||||
if (s == sizeof t / 5)
|
||||
R("limit %d\n", s);
|
||||
p *b = s[t], i, j;
|
||||
for (i = j = 0; i < 7 && !j; ++i)
|
||||
if (!(j = *a == 10 ? i : 0))
|
||||
*b++ = u | *a++;
|
||||
j - 5 || ++s;
|
||||
}
|
||||
q L(p *a, _ b) {
|
||||
for (_ l = 0, o = 0, k; l < s; o = 0) {
|
||||
for (_ j = 0; !o && j < 5 && (k = t[l][j]); ++j)
|
||||
i.c[j] && k - i.c[j] && ++o;
|
||||
for (_ j = 0; !o && j < 5 && (k = t[l][j]); ++j)
|
||||
i.a[k] && ++o;
|
||||
for (_ j = 0; !o && j < 5 && (k = t[l][j]); ++j)
|
||||
i.d[j] && !O(t[l], i.d[j]) && ++o;
|
||||
for (_ f = i.e; f-- && !o; )
|
||||
for (_ j = 0; !o && j < 5 && (k = t[l][j]); ++j)
|
||||
i.b[f][j] == k && ++o;
|
||||
if (!o) {
|
||||
for (_ j = 0; j < 5; ++j)
|
||||
o += t[l][j] == a[j];
|
||||
o = o == 5 ? b != 5 : 0;
|
||||
}
|
||||
o ? W(t[l], t[--s]) : ++l;
|
||||
}
|
||||
}
|
||||
_ e(_ W, _ O, _ R, _ D, _ *L, _ *E) {
|
||||
for (; O < D; )
|
||||
L[R++] = E[O++ + D * W];
|
||||
return R;
|
||||
}
|
||||
q S(_ O, _ *l) {
|
||||
for (_ *s = &a[a[O]], *e = a[-~O] + s - a[O]; s < e; ) {
|
||||
_ i = *s++,
|
||||
j = i & 15,
|
||||
k = l[i >>= 4] < l[j] ? k = l[i], l[i] = l[j], l[j] = k : i;
|
||||
}
|
||||
}
|
||||
_ o(_ W, _ O, _ R, _ D, _ *L, _ *E) {
|
||||
_ o = 0, w = 0;
|
||||
for (; o < D & w < D; )
|
||||
L[R++] = E[o + D * W] >= E[w + D * O]
|
||||
? E[o++ + D * W]
|
||||
: E[w++ + D * O];
|
||||
return e(O, w, e(W, o, R, D, L, E), D, L, E);
|
||||
}
|
||||
q l(_ n, _ *f) {
|
||||
for (_ *e = f + 26, i, j; f < e && *f > u; f += i) {
|
||||
for (i = 1, j = *f / u; i < n && f[i] >> 5 == j; )
|
||||
++i;
|
||||
for (j = 0; j < i; ++j)
|
||||
f[j] &= 31,
|
||||
f[j] |= a[f[j] + a[~-9]] << 5;
|
||||
S(i, f);
|
||||
}
|
||||
}
|
||||
q v(_ a, _ *w, _ *k) {
|
||||
o(2, 3, o(0, 1, 0, a, w, k), a, w, k);
|
||||
o(0, 1, 0, a + a, k, w);
|
||||
l(a, k);
|
||||
}
|
||||
p *E(p *d) {
|
||||
_ l, j, k = u, b[u], c[k];
|
||||
p *e[97][5] = { 0 } ;
|
||||
for (l = 0; l < k; ++l)
|
||||
c[l] = l;
|
||||
for (l = 0; l < s; ++l)
|
||||
for (_ j = 0; j < 5; ++j)
|
||||
c[t[l][j] - 97] += k;
|
||||
for (l = j = 7; j < 22; j += l)
|
||||
S(l, c + j - l);
|
||||
v(l, b, c);
|
||||
for (l = 0; l < k; ++l)
|
||||
b[c[l] & ~-k] = l;
|
||||
for (k *= 3, l = 0; l < s; ++l) {
|
||||
_ i = 0;
|
||||
for (_ j = 0; j < 5; ++j)
|
||||
i += b[t[l][j] - 97];
|
||||
if (i < k)
|
||||
for (_ j = 0; j < 5; ++j)
|
||||
e[i][j] || (e[i][j] = t[l], j = 4);
|
||||
}
|
||||
for (l = 0; l < k; ++l)
|
||||
for (p *b = 0, k = j = 0; j < 5 && (b = e[l][j]); k = !++j) {
|
||||
p c[32] = { 0 } ;
|
||||
d = *d - 120 ? d : b;
|
||||
if (s > 2)
|
||||
for (_ j = 0; j < 5; ++j)
|
||||
k += ++c[b[j] - 97] > 1;
|
||||
if (!k)
|
||||
return b;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
p *r(p *b) {
|
||||
_ k, l;
|
||||
for (_ j = k = l = 0; j < 5; ++j) {
|
||||
signed char n = b[j], o = b[j - ~5] + ~0x66;
|
||||
(o ? i.b[i.e] : i.c)[j] = n;
|
||||
!o ? i.a[n] = !++k : O(i.d, n) || (*(o < 0 ? &i.a[n] : &i.d[i.f++]) = l = n);
|
||||
}
|
||||
i.e += !!l;
|
||||
L(b, k);
|
||||
return E("xyzzy");
|
||||
}
|
||||
_ main(_ n, char **v) {
|
||||
p *j = i.c - 97, *l = j - 11;
|
||||
n - 2 ? R("usage: %s dict\n", *v) : 5;
|
||||
FILE *k = fopen(*++v, "r");
|
||||
if (!k)
|
||||
return perror(*v), 1;
|
||||
while (fgets(j, u ^ n, k))
|
||||
D(j);
|
||||
fclose(k);
|
||||
setbuf(stdout, 0);
|
||||
while (~-s) {
|
||||
printf("? ");
|
||||
while (~(n = getchar()) && n - 10 && l < j)
|
||||
*l++ = n;
|
||||
l < j && R("input: guess color\n");
|
||||
printf("%.5s\n", r(l = j + ~10));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,814 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<!-- START: two lines up starts content from: inc/top.default.html -->
|
||||
|
||||
<!-- END: this line ends content from: inc/top.default.html -->
|
||||
<!-- START: this line starts content from: inc/head.default.html -->
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../ioccc.css">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@100..900&display=swap" rel="stylesheet">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
<title>The International Obfuscated C Code Contest</title>
|
||||
<link rel="icon" type="image/x-icon" href="../../favicon.ico">
|
||||
<meta name="description" content="deobfuscated.md for 2024/burton">
|
||||
<meta name="keywords" content="IOCCC, 2024/burton, deobfuscated.md">
|
||||
</head>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
|
||||
<!-- END: this line ends content from: inc/head.default.html -->
|
||||
|
||||
<!-- -->
|
||||
<!-- This web page was formed via the tool: bin/gen-other-html.sh -->
|
||||
<!-- The content of main section of this web page came from: 2024/burton/deobfuscated.md -->
|
||||
<!-- -->
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<!-- !!! Do not modify this web page, instead modify the file: 2024/burton/deobfuscated.md !!! -->
|
||||
<!-- !!! Do not modify this web page, instead modify the file: 2024/burton/deobfuscated.md !!! -->
|
||||
<!-- !!! Do not modify this web page, instead modify the file: 2024/burton/deobfuscated.md !!! -->
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
|
||||
<!-- Markdown content was converted into HTML via the tool: bin/md2html.sh -->
|
||||
|
||||
<!-- START: this line starts content from: inc/body.default.html -->
|
||||
|
||||
<body>
|
||||
|
||||
<!-- END: this line ends content from: inc/body.default.html -->
|
||||
<!-- START: this line starts content from: inc/topbar.default.html -->
|
||||
|
||||
<div class="theader">
|
||||
<nav class="topbar">
|
||||
<div class="container">
|
||||
<div class="logo">
|
||||
<a href="../../index.html" class="logo-link">
|
||||
IOCCC
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="topbar-items">
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
Entries
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../years.html" class="sub-item-link">
|
||||
Winning entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../authors.html" class="sub-item-link">
|
||||
Winning authors
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../location.html" class="sub-item-link">
|
||||
Location of authors
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../bugs.html" class="sub-item-link">
|
||||
Bugs and (mis)features
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#fix_an_entry" class="sub-item-link">
|
||||
Fixing entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#fix_author" class="sub-item-link">
|
||||
Updating author info
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
Status
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../news.html" class="sub-item-link">
|
||||
News
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../status.html" class="sub-item-link">
|
||||
Contest status
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../next/rules.html" class="sub-item-link">
|
||||
IOCCC rules
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../next/guidelines.html" class="sub-item-link">
|
||||
IOCCC guidelines
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../markdown.html" class="sub-item-link">
|
||||
Markdown guidelines
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../SECURITY.html" class="sub-item-link">
|
||||
Security policy
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
FAQ
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html" class="sub-item-link">
|
||||
Frequently asked questions
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../quick-start.html#enter" class="sub-item-link">
|
||||
Enter the IOCCC
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#compiling" class="sub-item-link">
|
||||
Compiling entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#running_entries" class="sub-item-link">
|
||||
Running entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#help" class="sub-item-link">
|
||||
How to help
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
About
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../index.html" class="sub-item-link">
|
||||
Home page
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../social.html" class="sub-item-link">
|
||||
IOCCC social media
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../about.html" class="sub-item-link">
|
||||
About the IOCCC
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../judges.html" class="sub-item-link">
|
||||
The judges
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../thanks-for-help.html" class="sub-item-link">
|
||||
Thanks for the help
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../contact.html" class="sub-item-link">
|
||||
Contact us
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="header-mobile-menu">
|
||||
<noscript>
|
||||
<a href="../../nojs-menu.html" class="topbar-js-label">
|
||||
Please Enable JavaScript
|
||||
</a>
|
||||
</noscript>
|
||||
|
||||
<button id="header-open-menu-button" class="topbar-mobile-menu">
|
||||
<img
|
||||
src="../../png/hamburger-icon-open.png"
|
||||
alt="hamburger style menu icon - open state"
|
||||
width=48
|
||||
height=48>
|
||||
</button>
|
||||
|
||||
<button id="header-close-menu-button" class="hide-content">
|
||||
<img
|
||||
src="../../png/hamburger-icon-closed.png"
|
||||
alt="hamburger style menu icon - closed state"
|
||||
width=48
|
||||
height=48>
|
||||
</button>
|
||||
|
||||
<div id="mobile-menu-panel" class="hide-content">
|
||||
<div class="mobile-menu-container">
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
<div class="mobile-menu-item">
|
||||
Entries
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../years.html">
|
||||
Winning entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../authors.html">
|
||||
Winning authors
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../location.html">
|
||||
Location of authors
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../bugs.html">
|
||||
Bugs and (mis)features
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#fix_an_entry">
|
||||
Fixing entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#fix_author">
|
||||
Updating author info
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../thanks-for-help.html">
|
||||
Thanks for the help
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
|
||||
<div class="mobile-menu-item">
|
||||
Status
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../news.html">
|
||||
News
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../status.html">
|
||||
Contest status
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../next/rules.html">
|
||||
IOCCC rules
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../next/guidelines.html">
|
||||
IOCCC guidelines
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../markdown.html">
|
||||
Markdown guidelines
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../SECURITY.html">
|
||||
Security policy
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
<div class="mobile-menu-item">
|
||||
FAQ
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html">
|
||||
Frequently asked questions
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../quick-start.html#enter">
|
||||
Enter the IOCCC
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#compiling">
|
||||
Compiling entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#running_entries">
|
||||
Running entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#help">
|
||||
How to help
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
<div class="mobile-menu-item">
|
||||
About
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../index.html">
|
||||
Home page
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../social.html">
|
||||
IOCCC social media
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../about.html">
|
||||
About the IOCCC
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../judges.html">
|
||||
The judges
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../contact.html">
|
||||
Contact us
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var headerOpenMenuButton = document.getElementById("header-open-menu-button");
|
||||
var headerCloseMenuButton = document.getElementById("header-close-menu-button");
|
||||
var mobileMenuPanel = document.getElementById("mobile-menu-panel");
|
||||
|
||||
headerOpenMenuButton.addEventListener("click", () => {
|
||||
headerOpenMenuButton.classList.remove("topbar-mobile-menu");
|
||||
headerOpenMenuButton.classList.add("hide-content");
|
||||
|
||||
headerCloseMenuButton.classList.remove("hide-content");
|
||||
headerCloseMenuButton.classList.add("topbar-mobile-menu");
|
||||
|
||||
mobileMenuPanel.classList.remove("hide-content");
|
||||
mobileMenuPanel.classList.add("topbar-mobile-panel");
|
||||
});
|
||||
|
||||
headerCloseMenuButton.addEventListener("click", () => {
|
||||
headerCloseMenuButton.classList.remove("topbar-mobile-menu");
|
||||
headerCloseMenuButton.classList.add("hide-content");
|
||||
|
||||
mobileMenuPanel.classList.add("hide-content");
|
||||
mobileMenuPanel.classList.remove("topbar-mobile-panel");
|
||||
|
||||
headerOpenMenuButton.classList.add("topbar-mobile-menu");
|
||||
headerOpenMenuButton.classList.remove("hide-content");
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- END: this line ends content from: inc/topbar.default.html -->
|
||||
<!-- START: this line starts content from: inc/header.default.html -->
|
||||
|
||||
<div class="header">
|
||||
<a href="../../2011/zucker/index.html">
|
||||
<img src="../../png/ioccc.png"
|
||||
alt="IOCCC image by Matt Zucker"
|
||||
width=300
|
||||
height=110>
|
||||
</a>
|
||||
<h1>The International Obfuscated C Code Contest</h1>
|
||||
<h2>deobfuscated.html for 2024/burton</h2>
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/header.default.html -->
|
||||
<!-- START: this line starts content from: inc/navbar.up2index.html -->
|
||||
|
||||
<div class="navbar">
|
||||
<a class="Left" href="index.html">↑ jump to 2024/burton/index.html ↑</a>
|
||||
<a class="Right" href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fwww.ioccc.org%2F2024%2Fburton%2Fdeobfuscated.html">✓</a>
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/navbar.up2index.html -->
|
||||
<!-- START: this line starts content from: inc/before-content.default.html -->
|
||||
|
||||
<div class="content" id="content">
|
||||
|
||||
<!-- END: this line ends content from: inc/before-content.default.html -->
|
||||
<!-- START: this line starts content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||||
|
||||
<!-- BEFORE: 1st line of markdown file: 2024/burton/deobfuscated.md -->
|
||||
<h1 id="do-not-read-this-if-you-want-to-figure-it-out-yourself">Do not read this if you want to figure it out yourself!</h1>
|
||||
<p>The file <code>deobfuscated.c</code> is simply a pretty-printed version of
|
||||
<code>prog.c</code> with the macros expanded. It is hopefully just as
|
||||
difficult to understand as the original presentation:
|
||||
obfuscation is not just presentation, after all.</p>
|
||||
<p>If you read further, the remainder talks about how the code
|
||||
works. If you want to figure it out yourself, stop reading here
|
||||
and do look at <code>deobfuscated.c</code>.</p>
|
||||
<h2 id="read-dictionary">Read Dictionary</h2>
|
||||
<p>The program begins by reading junk ;-) from the dictionary and processing
|
||||
via <code>D()</code>. The words are stored in <code>t[][]</code>, counted by <code>s</code> and <code>D()</code> ensures
|
||||
this never has buffer overflow. Notice the swap of index and array in <code>s[t]</code>.
|
||||
It also ensures only 5 letter words are selected from the dictionary,
|
||||
and folds uppercase to lowercase. Each call of <code>D()</code> handles one word.</p>
|
||||
<p>NB: if the dictionary has, for instance, “ARRAY” and “array” and “Array”,
|
||||
there will be 3 copies of “array” stored in <code>t[][]</code>.
|
||||
This will degrade performance and may cause a malfunction of the algorithm,
|
||||
and definitely if the target word is “array”. Thus the <code>makefile</code> builds
|
||||
<code>usdw</code> with capital letters removed (avoiding this problem completely).
|
||||
However, if there are duplicate words in the dictionary, use another.</p>
|
||||
<h2 id="user-input">User Input</h2>
|
||||
<p>After the dictionary is read, it is time to prompt the user for the
|
||||
input guess. This happens in <code>main()</code>. The input buffer is the upper
|
||||
half of <code>i.a</code>, which is never used (ASCII lowercase letters only).
|
||||
The newline is ignored by <code>n - 10</code>, at most 11 characters (<code>l < j</code>)
|
||||
can be input, and EOF terminates the input loop.</p>
|
||||
<p>Here is the explanation of how <code>i.c - 97</code> works to get an input buffer.
|
||||
Assume <code>struct i</code> has the address 1000, then <code>i.a</code> begins at 1000.
|
||||
<code>i.b</code> begins at 1257. <code>i.c</code> begins at 9*5 = 45 + 1257 = 1302.
|
||||
1302 - 97 = 1205. Therefore, the <code>i.c - 97</code> sets the input buffer at
|
||||
<code>&i.a[205]</code>, ASCII lowercase input ends at <code>i.a[123]</code>, and there are
|
||||
53 characters before <code>i.b</code> is overwritten - plenty of room for the user IO.
|
||||
Why 97? The expression <code>x - 97</code> is used several times in the code,
|
||||
leading to some confusion on the reason for the value.</p>
|
||||
<p>Note that this abuse is what draws a compiler complaint, requiring:</p>
|
||||
<pre><code> -Wno-array-bounds-pointer-arithmetic</code></pre>
|
||||
<p>It is safe. It works. There is no problem here, but the compiler
|
||||
does not know this.</p>
|
||||
<h2 id="process-user-input">Process User Input</h2>
|
||||
<p>Once the user input is received, the program calls <code>r()</code>, which populates
|
||||
<code>struct i</code> with the guesses. This serves to set the patterns known
|
||||
and impossible, as well as letters used and required (remember, this is
|
||||
hard mode Wordle, which requires you to use all green letters in the
|
||||
same place for all subsequent guesses). <code>r()</code> returns the next word
|
||||
to guess via <code>E()</code> (aka choose() - see below).</p>
|
||||
<p>Within <code>r()</code>, it is important to understand the ASCII values for g, y and b.</p>
|
||||
<pre><code> b 98
|
||||
g 103
|
||||
y 121</code></pre>
|
||||
<p>Within <code>r()</code>, <code>n</code> is the guessed letter, and <code>o</code> is color - 103.
|
||||
If <code>o</code> is greater than zero (121-103), this guess is correct, but
|
||||
incorrect location (yellow). If it is less than zero (98-103),
|
||||
this guess is not possible (black). If it is zero (103-103),
|
||||
it is the correct letter in the correct location (green).</p>
|
||||
<p><code>struct i</code> can be re-written this way:</p>
|
||||
<pre><code> struct {
|
||||
char black[256]; // wrong letters guessed so far
|
||||
char words[9][5]; // words used in guesses so far
|
||||
char green[5]; // correct letters (must reuse these)
|
||||
char yellow[5]; // incorrect letters (impossible positions)
|
||||
int num_guesses;
|
||||
int num_yellow;
|
||||
} i;</code></pre>
|
||||
<p>And <code>r()</code> can be rewritten:</p>
|
||||
<pre><code> char *r(char *input) {
|
||||
int num_green = 0, l = 0;
|
||||
|
||||
for (int j = 0; j < 5; ++j) {
|
||||
char n = input[j];
|
||||
signed char o = input[j + 6] - 103; // j - ~5 = j - -6 == j + 6
|
||||
|
||||
// if this is a correct guess
|
||||
if (o == 0) {
|
||||
i.green[j] = n;
|
||||
i.black[n] = 0; // remove this from black
|
||||
++num_green;
|
||||
|
||||
} else {
|
||||
i.words[i.num_guesses][j] = n;
|
||||
|
||||
// if not already a yellow letter
|
||||
if (memchr(i.yellow, n, 5) == NULL) {
|
||||
l = n;
|
||||
if (o < 0) i.black[n] = n; // black, impossible
|
||||
else i.yellow[i.num_yellow++] = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// l is 0 if all letters correct, else l = n
|
||||
i.num_guesses += l > 0 ? 1 : 0;
|
||||
filter(input, num_green);
|
||||
return choose("xyzzy");
|
||||
}</code></pre>
|
||||
<h2 id="filter">Filter</h2>
|
||||
<p>The next step is to remove the impossible words from the in-memory dictionary.
|
||||
This is handled by <code>L()</code>. <code>L()</code> iterates over all the remaining words in the
|
||||
dictionary. <code>L()</code> runs a number of filters, and if the word is plausible,
|
||||
it is skipped, and if impossible, the current word is replaced from the end
|
||||
of the list. This prevents holes from appearing in the dictionary, and keeps
|
||||
the count accurate. The important action is carried out in the expression
|
||||
<code>o ? W(t[l], t[--s]) : ++l</code>. That is, if <code>o</code> is true, the word is replaced
|
||||
by the end of the list, else the word is skipped. Note in particular the
|
||||
expressions <code>--s</code> and <code>++l</code> (decrement and replace, or skip, respectively).</p>
|
||||
<p>Said another way, think of <code>W()</code> as an analog of <code>strncpy()</code>. Thus, if <code>o</code>
|
||||
is true, then <code>strncpy(t[l], t[--s], 5)</code>, which overwrites the current word
|
||||
with the end of the list, and decrements the number of entries. Note the
|
||||
end of the list is not <code>t[s]</code>, but <code>t[s-1]</code>, thus the pre-decrement achieves
|
||||
both the desired index and decrements the count.</p>
|
||||
<h2 id="word-selection">Word Selection</h2>
|
||||
<p>After the words are filtered, then comes the hard part: selecting which word
|
||||
to guess next! This is handled by <code>E()</code>, by far the most interesting routine
|
||||
in the code.</p>
|
||||
<p>The loops in order:</p>
|
||||
<ul>
|
||||
<li>init <code>c[]</code> with ordinal values (a-z plus 6 slop) in the lower 5 bits</li>
|
||||
<li>in the higher order bits, count the frequency of all remaining letters</li>
|
||||
<li>sort by the frequency of letters in 3 sets of 7 (21 not 26!)</li>
|
||||
<li>merge the separate sorts into one via <code>v()</code> (see below on merging)</li>
|
||||
<li>for letters with same freq, re-sort by English frequency values <code>l()</code></li>
|
||||
<li>using the sorted list, put the corresponding ordinals into <code>b[]</code></li>
|
||||
<li>for each word, if scores below 97, put into <code>e[][]</code> (low score wins)</li>
|
||||
<li>allow up to 5 duplicate scores, only keep first 5 words with same score</li>
|
||||
<li>search the list for the lowest scoring word (best match)</li>
|
||||
<li>if more than 2 words remain, find first word without duplicate letters</li>
|
||||
<li>return whatever we found, if anything</li>
|
||||
</ul>
|
||||
<p>The weakness in this scheme is at least two-fold: 1) if there are more than 5
|
||||
words with the same score, words that come later are not selected, and 2) all
|
||||
words with the same score are considered the same, without regard to letter
|
||||
order or letter frequencies. I have run no experiments here,
|
||||
but I think this is an area for minor improvement.</p>
|
||||
<h2 id="network-sort">Network Sort</h2>
|
||||
<p>Network sort<a href="https://en.wikipedia.org/wiki/Sorting_network">1</a> is a simple, compact, constant time sort with minimal compares.</p>
|
||||
<p>It is obfuscated in a number of ways.
|
||||
The routine <code>S()</code> looks into the array <code>a[]</code> and determines the number of
|
||||
elements to sort via the differences in the initial values of <code>a[]</code>.
|
||||
Consider the possible number of values given in <code>O</code> from 0 (zero) to 7:
|
||||
if <code>O</code> is 0 or 1, no sort is necessary (an empty list cannot be sorted,
|
||||
and a list of one does not need to be sorted):</p>
|
||||
<pre><code> O+1 O
|
||||
a[1] - a[0] = 9 - 9 = 0
|
||||
a[2] - a[1] = 9 - 9 = 0
|
||||
a[3] - a[2] = 10 - 9 = 1</code></pre>
|
||||
<p>If <code>O</code> is 2, then only one compare and swap is necessary. Why is this?
|
||||
Consider how many compares are necessary to determine the proper order of
|
||||
variables A and B: one test and one possible swap are all that is needed.
|
||||
If A > B, swap. If A <= B, then no swap and the list is already ordered.</p>
|
||||
<p>Where is this calculation done? Address arithmetic FTW!
|
||||
<code>e = a[-~O] + s - a[O]</code>. <code>-~O</code> is the identity <code>O+1</code>.
|
||||
So this expression restated is <code>e = s + a[O+1] - a[O]</code>.
|
||||
If you look at the first numbers in <code>a[]</code> and their offsets (table 1):</p>
|
||||
<pre><code> table 1
|
||||
offsets: 0 1 2 3 4 5 6 7 8
|
||||
values : 9 9 9 10 13 18 27 39 55</code></pre>
|
||||
<p>You can see the expression selects for O in 0..7 (table 2):</p>
|
||||
<pre><code> // table 2
|
||||
a[0+1] - a[0] = 9 - 9 = 0 // 0 selects no compares
|
||||
a[1+1] - a[1] = 9 - 9 = 0 // 1 selects no compares
|
||||
a[2+1] - a[2] = 10 - 9 = 1 // 2 selects 1 compare
|
||||
a[3+1] - a[3] = 13 - 10 = 3 // 3 selects 3 compares
|
||||
a[4+1] - a[4] = 18 - 13 = 5 // 4 selects 5 compares
|
||||
a[5+1] - a[5] = 27 - 18 = 9 // 5 selects 9 compares
|
||||
a[6+1] - a[6] = 39 - 27 = 12 // 6 selects 12 compares
|
||||
a[7+1] - a[7] = 55 - 39 = 16 // 7 selects 16 compares</code></pre>
|
||||
<p>What are we comparing? <code>s</code> ranges from <code>&a[a[O]]</code> to <code>&a[a[O+1]]</code>.</p>
|
||||
<pre><code> O expr
|
||||
0 9 - 9 = 0: no compares
|
||||
1 9 - 9 = 0: no compares
|
||||
2 10 - 9 = 1: &a[a[9]] + 1 or the set { 1 }
|
||||
3 13 - 10 = 3: &a[a[10]] + 3 or the set { 18, 2, 1 }
|
||||
4 18 - 13 = 5: &a[a[13]] + 5 or the set { 1, 35, 2, 19, 18 }
|
||||
...
|
||||
7 55 - 39 = 16: &a[a[39]] + 16 or the set
|
||||
{ 18, 52, 86, 2, 53, 70, 1, 69,
|
||||
38, 4, 21, 3, 37, 19, 36, 35 }</code></pre>
|
||||
<p>So what do these numbers mean for sorting? Translate them to hex:</p>
|
||||
<pre><code> { 0x12, 0x34, 0x56, 0x02, 0x35, 0x46, 0x01, 0x45,
|
||||
0x26, 0x04, 0x15, 0x03, 0x25, 0x13, 0x24, 0x23 }</code></pre>
|
||||
<p>This compact arrangement can be split into high and low nibbles:</p>
|
||||
<pre><code> { (1,2), (3,4), (5,6), (0,2), (3,5), ... }</code></pre>
|
||||
<p>which means compare and maybe swap (keeping order low to high):</p>
|
||||
<pre><code> if (s[1] > s[2]) swap();
|
||||
if (s[3] > s[4]) swap();
|
||||
if (s[5] > s[6]) swap();
|
||||
if (s[0] > s[2]) swap();
|
||||
if (s[3] > s[5]) swap();
|
||||
....</code></pre>
|
||||
<p>For instance, when sorting 7 elements, start from <code>a[a[7]]</code> (39) until
|
||||
<code>a[a[8]]</code> (55), or 16 elements starting at <code>a[39]</code>.</p>
|
||||
<h2 id="the-array-a-explained-finally">The Array a[] Explained, Finally</h2>
|
||||
<p>The first set of 9 numbers are both the lengths AND the start and end indexes
|
||||
into the array <code>a[]</code>, as explained above in the Network Sort. The second set
|
||||
of numbers runs from indexes 9 through 54, and are the Network Sort comparison
|
||||
values. At index 55 begins the third part of the array. The final 26 values
|
||||
encode the inverse frequency of letters in the English language. The first
|
||||
value is 25 for the letter ‘a’. If you count, then 26 is for the letter ‘e’,
|
||||
the most common letter in the English language
|
||||
(or at least for the dictionary used).</p>
|
||||
<p>This final set of letters is used in the routine <code>l()</code>. Notice the expression:
|
||||
<code>a[f[j] + a[~-9]]</code>; <code>a[~-9]</code> is an obscure way of writing <code>a[8]</code>, which is the
|
||||
value 55. So <code>a[f[j]]</code> is an index into this frequency array, offset by 55.
|
||||
Why is there a <code><< 5</code>? Again, the letter offsets are in the lowest 5 bits,
|
||||
and the counts of the letters is in the upper bits.</p>
|
||||
<p>The reason for putting the counts in the upper bits is simple: it makes the
|
||||
value larger for larger counts. Thus, sorting based upon frequency is natural.</p>
|
||||
<h2 id="merge-sort">Merge Sort</h2>
|
||||
<p>The network sort as implemented handles up to 7 letters in 3 calls.
|
||||
26 / 7 = 3 r 5. Thus, we need to merge up to 4 sets of 7 letters.
|
||||
This merge is handled by <code>v()</code>, which calls <code>o()</code> 3 times, once recursively.
|
||||
This is followed by a rearrangement handled in <code>l()</code>. This last step finds
|
||||
all the letters with the same frequency, then sorts them according to their
|
||||
English frequency.</p>
|
||||
<p>Back to the merge sort, which is really handled in <code>o()</code>. This is rather
|
||||
difficult to follow. The first call to <code>o()</code> is within the argument list
|
||||
to the second call. The first call has arguments
|
||||
W=0, O=1, R=0, D=a, L=w, E=k; and <code>v()</code> was called with <code>v(l=7, w=b, k=c)</code>.
|
||||
This first merge pass copies to: <code>L[R]</code> (<code>b[0]</code>) and selects from either
|
||||
<code>c[o]</code> or <code>c[w]</code> depending upon which is greater or equal. That is, it merges
|
||||
two 7 letter arrays into a single 14 element array twice, then it merges two 14
|
||||
element arrays into a single 28 element array. Note on the third call
|
||||
to <code>o()</code>, the last two arguments are swapped, which puts the final sort
|
||||
into <code>c[]</code>.</p>
|
||||
<p>Below is a hopefully easier way to read the merge sort code:</p>
|
||||
<pre><code> // merge residual
|
||||
int e(int mult_o, int start, int to, int off, int *a1, int *a2)
|
||||
{
|
||||
for (; start < off; )
|
||||
a1[to++] = a2[start++ + off * mult_o];
|
||||
return to;
|
||||
}
|
||||
|
||||
// merge sort
|
||||
int o(int mult_o, int mult_w, int to, int len, int *a1, int *a2)
|
||||
{
|
||||
// first call: mult_o = 0, mult_w = 1, to = 0, len = 7, a1=b, a2=c
|
||||
// second: mult_o = 2, mult_w = 3, to = N, len = 7, a1=b, a2=c
|
||||
// third: mult_o = 0, mult_w = 1, to = 0, len = 14, a1=c, a2=b
|
||||
|
||||
int o = 0, w = 0;
|
||||
for (; o < len && w < len; ) {
|
||||
|
||||
// first call: to=0, len=7, mult_o=0, mult_w=1
|
||||
// a1[0++] = a2[0 + 7*0] >= a2[0 + 7*1]
|
||||
// ? a2[0 + 7*0] : a2[0 + 7*1]
|
||||
// a1[0++] = a2[0] > a2[7] ? a[0++] : a2[7++]
|
||||
|
||||
// second call: to=14, len=7, mult_o=2, mult_w=3
|
||||
// a1[14++] = a2[0 + 7*2] >= a2[0 + 7*3]
|
||||
// ? a2[0 + 7*2] : a2[0 + 7*3]
|
||||
// a1[14++] = a2[14] > a2[21] ? a2[14++] : a2[21++]
|
||||
|
||||
// third call: to=0, len=14, mult_o=0, mult_w=1
|
||||
// a1[0++] = a2[0 + 14*0] >= a2[0 + 14*1]
|
||||
// ? a2[0 + 14*0] : a2[0 + 14*1];
|
||||
// a1[0++] = a[0] >= a2[14] ? a2[0++] : a2[14++]
|
||||
|
||||
a1[to++] = a2[o + len * mult_o] >= a2[w + len * mult_w]
|
||||
? a2[o++ + len * mult_o]
|
||||
: a2[w++ + len * mult_w]
|
||||
}
|
||||
int n = e(mult_o, o, to, len, a1, a2);
|
||||
return e(mult_w, w, n, len, a1, a2);
|
||||
}</code></pre>
|
||||
<p>Isn’t that as clear as mud? It is far easier to understand the flow when
|
||||
you add <code>printf()</code> statements to follow the logic. Included is the file
|
||||
<code>deobfuscated.c</code> for you to start with.</p>
|
||||
<h2 id="why-name-the-functions-as-they-are">Why name the functions as they are?</h2>
|
||||
<p>Run <code>make spoiler</code>.</p>
|
||||
<h2 id="bug-explained">Bug Explained</h2>
|
||||
<p>If you followed the above explanation, you will notice that only the first
|
||||
21 of 26 letters are sorted (ignoring { v, w, x, y, z }. But 28 of 26 letters
|
||||
are merge sorted. It was observed the program performs worse if all 26 letters
|
||||
are sorted (which tends to over-favor <code>y</code>).
|
||||
But some words do have <code>y</code> in them, which is why the merge sort takes 28
|
||||
letters (including the ASCII values <code>{</code> and <code>|</code>), so all letters are still
|
||||
selected when appropriate. The merge sort puts the { v, w, x, y, z }
|
||||
letters into the proper frequency set, eventually.</p>
|
||||
<p>If you change the loop value <code>22</code> to <code>32</code>, then all letters are sorted,
|
||||
the program will work correctly, but it will change the performance
|
||||
of the algorithm to be slightly worse than the original.</p>
|
||||
<p>If you change any values in the array <code>a[]</code>,
|
||||
the program will no longer work correctly.</p>
|
||||
<p>Finally, what is the significance of the array size 78557?
|
||||
<code>usdw</code> only needs 8506. Why was such a large value used?
|
||||
<!-- AFTER: last line of markdown file: 2024/burton/deobfuscated.md --></p>
|
||||
|
||||
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||||
<!-- START: this line starts content from: inc/after-content.default.html -->
|
||||
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/after-content.default.html -->
|
||||
<!-- START: this line starts content from: inc/footer.default.html -->
|
||||
|
||||
<!--
|
||||
|
||||
Copyright © 1984-2025 by Landon Curt Noll. All Rights Reserved.
|
||||
|
||||
You are free to share and adapt this file under the terms of this license:
|
||||
|
||||
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
||||
|
||||
For more information, see:
|
||||
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
-->
|
||||
|
||||
<div class="footer">
|
||||
|
||||
<div id="copyright"><h3>Copyright © 1984-2025 by Landon Curt Noll:
|
||||
<a href="https://creativecommons.org/faq/#what-does-some-rights-reserved-mean"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer">Some Rights Reserved</a></h3>
|
||||
<p>
|
||||
This work is <b>licensed by Landon Curt Noll</b> under
|
||||
<b><a href="https://creativecommons.org/licenses/by-sa/4.0/?ref=chooser-v1"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer"
|
||||
style="display:inline-block;">CC BY-SA 4.0</a></b>.
|
||||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||||
src="../../png/cc.png"
|
||||
alt="cc inside circle symbol">
|
||||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||||
src="../../png/by.png"
|
||||
alt="person inside circle symbol">
|
||||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||||
src="../../png/sa.png"
|
||||
alt="arrow looping back on itself inside circle symbol"><br>
|
||||
You should <b>carefully review</b> the
|
||||
<b><a href="https://creativecommons.org/licenses/by-sa/4.0/legalcode.en"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer">CC BY-SA 4.0 LEGAL CODE</a></b>
|
||||
before using the licensed material.<br>
|
||||
You may wish to review the
|
||||
<b><a href="../../license.html"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer">highlights of some of the key features and terms</a></b>
|
||||
of <b>CC BY-SA 4.0</b>.<br>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="coda"><h3>Coda</h3>
|
||||
<p>
|
||||
<a href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fwww.ioccc.org%2F2024%2Fburton%2Fdeobfuscated.html" rel="nofollow">Nu HTML check this web page</a><br>
|
||||
<a href="#top">Jump to top</a> <a href="#content">Jump to Content</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/footer.default.html -->
|
||||
<!-- START: this line starts content from: inc/bottom.default.html -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<!-- END: this line ends content from: inc/bottom.default.html -->
|
||||
@@ -0,0 +1,382 @@
|
||||
# Do not read this if you want to figure it out yourself! #
|
||||
|
||||
The file `deobfuscated.c` is simply a pretty-printed version of
|
||||
`prog.c` with the macros expanded. It is hopefully just as
|
||||
difficult to understand as the original presentation:
|
||||
obfuscation is not just presentation, after all.
|
||||
|
||||
If you read further, the remainder talks about how the code
|
||||
works. If you want to figure it out yourself, stop reading here
|
||||
and do look at `deobfuscated.c`.
|
||||
|
||||
|
||||
## Read Dictionary ##
|
||||
|
||||
The program begins by reading junk ;-) from the dictionary and processing
|
||||
via `D()`. The words are stored in `t[][]`, counted by `s` and `D()` ensures
|
||||
this never has buffer overflow. Notice the swap of index and array in `s[t]`.
|
||||
It also ensures only 5 letter words are selected from the dictionary,
|
||||
and folds uppercase to lowercase. Each call of `D()` handles one word.
|
||||
|
||||
NB: if the dictionary has, for instance, "ARRAY" and "array" and "Array",
|
||||
there will be 3 copies of "array" stored in `t[][]`.
|
||||
This will degrade performance and may cause a malfunction of the algorithm,
|
||||
and definitely if the target word is "array". Thus the `makefile` builds
|
||||
`usdw` with capital letters removed (avoiding this problem completely).
|
||||
However, if there are duplicate words in the dictionary, use another.
|
||||
|
||||
|
||||
## User Input ##
|
||||
|
||||
After the dictionary is read, it is time to prompt the user for the
|
||||
input guess. This happens in `main()`. The input buffer is the upper
|
||||
half of `i.a`, which is never used (ASCII lowercase letters only).
|
||||
The newline is ignored by `n - 10`, at most 11 characters (`l < j`)
|
||||
can be input, and EOF terminates the input loop.
|
||||
|
||||
Here is the explanation of how `i.c - 97` works to get an input buffer.
|
||||
Assume `struct i` has the address 1000, then `i.a` begins at 1000.
|
||||
`i.b` begins at 1257. `i.c` begins at 9*5 = 45 + 1257 = 1302.
|
||||
1302 - 97 = 1205. Therefore, the `i.c - 97` sets the input buffer at
|
||||
`&i.a[205]`, ASCII lowercase input ends at `i.a[123]`, and there are
|
||||
53 characters before `i.b` is overwritten - plenty of room for the user IO.
|
||||
Why 97? The expression `x - 97` is used several times in the code,
|
||||
leading to some confusion on the reason for the value.
|
||||
|
||||
Note that this abuse is what draws a compiler complaint, requiring:
|
||||
|
||||
```
|
||||
-Wno-array-bounds-pointer-arithmetic
|
||||
```
|
||||
|
||||
It is safe. It works. There is no problem here, but the compiler
|
||||
does not know this.
|
||||
|
||||
|
||||
## Process User Input ##
|
||||
|
||||
Once the user input is received, the program calls `r()`, which populates
|
||||
`struct i` with the guesses. This serves to set the patterns known
|
||||
and impossible, as well as letters used and required (remember, this is
|
||||
hard mode Wordle, which requires you to use all green letters in the
|
||||
same place for all subsequent guesses). `r()` returns the next word
|
||||
to guess via `E()` (aka choose() - see below).
|
||||
|
||||
Within `r()`, it is important to understand the ASCII values for g, y and b.
|
||||
|
||||
```
|
||||
b 98
|
||||
g 103
|
||||
y 121
|
||||
```
|
||||
|
||||
Within `r()`, `n` is the guessed letter, and `o` is color - 103.
|
||||
If `o` is greater than zero (121-103), this guess is correct, but
|
||||
incorrect location (yellow). If it is less than zero (98-103),
|
||||
this guess is not possible (black). If it is zero (103-103),
|
||||
it is the correct letter in the correct location (green).
|
||||
|
||||
`struct i` can be re-written this way:
|
||||
|
||||
``` <!---c-->
|
||||
struct {
|
||||
char black[256]; // wrong letters guessed so far
|
||||
char words[9][5]; // words used in guesses so far
|
||||
char green[5]; // correct letters (must reuse these)
|
||||
char yellow[5]; // incorrect letters (impossible positions)
|
||||
int num_guesses;
|
||||
int num_yellow;
|
||||
} i;
|
||||
```
|
||||
|
||||
And `r()` can be rewritten:
|
||||
|
||||
``` <!---c-->
|
||||
char *r(char *input) {
|
||||
int num_green = 0, l = 0;
|
||||
|
||||
for (int j = 0; j < 5; ++j) {
|
||||
char n = input[j];
|
||||
signed char o = input[j + 6] - 103; // j - ~5 = j - -6 == j + 6
|
||||
|
||||
// if this is a correct guess
|
||||
if (o == 0) {
|
||||
i.green[j] = n;
|
||||
i.black[n] = 0; // remove this from black
|
||||
++num_green;
|
||||
|
||||
} else {
|
||||
i.words[i.num_guesses][j] = n;
|
||||
|
||||
// if not already a yellow letter
|
||||
if (memchr(i.yellow, n, 5) == NULL) {
|
||||
l = n;
|
||||
if (o < 0) i.black[n] = n; // black, impossible
|
||||
else i.yellow[i.num_yellow++] = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// l is 0 if all letters correct, else l = n
|
||||
i.num_guesses += l > 0 ? 1 : 0;
|
||||
filter(input, num_green);
|
||||
return choose("xyzzy");
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Filter ##
|
||||
|
||||
The next step is to remove the impossible words from the in-memory dictionary.
|
||||
This is handled by `L()`. `L()` iterates over all the remaining words in the
|
||||
dictionary. `L()` runs a number of filters, and if the word is plausible,
|
||||
it is skipped, and if impossible, the current word is replaced from the end
|
||||
of the list. This prevents holes from appearing in the dictionary, and keeps
|
||||
the count accurate. The important action is carried out in the expression
|
||||
`o ? W(t[l], t[--s]) : ++l`. That is, if `o` is true, the word is replaced
|
||||
by the end of the list, else the word is skipped. Note in particular the
|
||||
expressions `--s` and `++l` (decrement and replace, or skip, respectively).
|
||||
|
||||
Said another way, think of `W()` as an analog of `strncpy()`. Thus, if `o`
|
||||
is true, then `strncpy(t[l], t[--s], 5)`, which overwrites the current word
|
||||
with the end of the list, and decrements the number of entries. Note the
|
||||
end of the list is not `t[s]`, but `t[s-1]`, thus the pre-decrement achieves
|
||||
both the desired index and decrements the count.
|
||||
|
||||
|
||||
## Word Selection ##
|
||||
|
||||
After the words are filtered, then comes the hard part: selecting which word
|
||||
to guess next! This is handled by `E()`, by far the most interesting routine
|
||||
in the code.
|
||||
|
||||
The loops in order:
|
||||
|
||||
- init `c[]` with ordinal values (a-z plus 6 slop) in the lower 5 bits
|
||||
- in the higher order bits, count the frequency of all remaining letters
|
||||
- sort by the frequency of letters in 3 sets of 7 (21 not 26!)
|
||||
- merge the separate sorts into one via `v()` (see below on merging)
|
||||
- for letters with same freq, re-sort by English frequency values `l()`
|
||||
- using the sorted list, put the corresponding ordinals into `b[]`
|
||||
- for each word, if scores below 97, put into `e[][]` (low score wins)
|
||||
- allow up to 5 duplicate scores, only keep first 5 words with same score
|
||||
- search the list for the lowest scoring word (best match)
|
||||
- if more than 2 words remain, find first word without duplicate letters
|
||||
- return whatever we found, if anything
|
||||
|
||||
The weakness in this scheme is at least two-fold: 1) if there are more than 5
|
||||
words with the same score, words that come later are not selected, and 2) all
|
||||
words with the same score are considered the same, without regard to letter
|
||||
order or letter frequencies. I have run no experiments here,
|
||||
but I think this is an area for minor improvement.
|
||||
|
||||
|
||||
## Network Sort ##
|
||||
|
||||
Network sort[1] is a simple, compact, constant time sort with minimal compares.
|
||||
|
||||
It is obfuscated in a number of ways.
|
||||
The routine `S()` looks into the array `a[]` and determines the number of
|
||||
elements to sort via the differences in the initial values of `a[]`.
|
||||
Consider the possible number of values given in `O` from 0 (zero) to 7:
|
||||
if `O` is 0 or 1, no sort is necessary (an empty list cannot be sorted,
|
||||
and a list of one does not need to be sorted):
|
||||
|
||||
```
|
||||
O+1 O
|
||||
a[1] - a[0] = 9 - 9 = 0
|
||||
a[2] - a[1] = 9 - 9 = 0
|
||||
a[3] - a[2] = 10 - 9 = 1
|
||||
```
|
||||
|
||||
If `O` is 2, then only one compare and swap is necessary. Why is this?
|
||||
Consider how many compares are necessary to determine the proper order of
|
||||
variables A and B: one test and one possible swap are all that is needed.
|
||||
If A > B, swap. If A <= B, then no swap and the list is already ordered.
|
||||
|
||||
Where is this calculation done? Address arithmetic FTW!
|
||||
`e = a[-~O] + s - a[O]`. `-~O` is the identity `O+1`.
|
||||
So this expression restated is `e = s + a[O+1] - a[O]`.
|
||||
If you look at the first numbers in `a[]` and their offsets (table 1):
|
||||
|
||||
```
|
||||
table 1
|
||||
offsets: 0 1 2 3 4 5 6 7 8
|
||||
values : 9 9 9 10 13 18 27 39 55
|
||||
```
|
||||
|
||||
You can see the expression selects for O in 0..7 (table 2):
|
||||
|
||||
``` <!---c-->
|
||||
// table 2
|
||||
a[0+1] - a[0] = 9 - 9 = 0 // 0 selects no compares
|
||||
a[1+1] - a[1] = 9 - 9 = 0 // 1 selects no compares
|
||||
a[2+1] - a[2] = 10 - 9 = 1 // 2 selects 1 compare
|
||||
a[3+1] - a[3] = 13 - 10 = 3 // 3 selects 3 compares
|
||||
a[4+1] - a[4] = 18 - 13 = 5 // 4 selects 5 compares
|
||||
a[5+1] - a[5] = 27 - 18 = 9 // 5 selects 9 compares
|
||||
a[6+1] - a[6] = 39 - 27 = 12 // 6 selects 12 compares
|
||||
a[7+1] - a[7] = 55 - 39 = 16 // 7 selects 16 compares
|
||||
```
|
||||
|
||||
What are we comparing? `s` ranges from `&a[a[O]]` to `&a[a[O+1]]`.
|
||||
|
||||
```
|
||||
O expr
|
||||
0 9 - 9 = 0: no compares
|
||||
1 9 - 9 = 0: no compares
|
||||
2 10 - 9 = 1: &a[a[9]] + 1 or the set { 1 }
|
||||
3 13 - 10 = 3: &a[a[10]] + 3 or the set { 18, 2, 1 }
|
||||
4 18 - 13 = 5: &a[a[13]] + 5 or the set { 1, 35, 2, 19, 18 }
|
||||
...
|
||||
7 55 - 39 = 16: &a[a[39]] + 16 or the set
|
||||
{ 18, 52, 86, 2, 53, 70, 1, 69,
|
||||
38, 4, 21, 3, 37, 19, 36, 35 }
|
||||
```
|
||||
|
||||
So what do these numbers mean for sorting? Translate them to hex:
|
||||
|
||||
``` <!---c-->
|
||||
{ 0x12, 0x34, 0x56, 0x02, 0x35, 0x46, 0x01, 0x45,
|
||||
0x26, 0x04, 0x15, 0x03, 0x25, 0x13, 0x24, 0x23 }
|
||||
```
|
||||
|
||||
This compact arrangement can be split into high and low nibbles:
|
||||
|
||||
```
|
||||
{ (1,2), (3,4), (5,6), (0,2), (3,5), ... }
|
||||
```
|
||||
|
||||
which means compare and maybe swap (keeping order low to high):
|
||||
|
||||
``` <!---c-->
|
||||
if (s[1] > s[2]) swap();
|
||||
if (s[3] > s[4]) swap();
|
||||
if (s[5] > s[6]) swap();
|
||||
if (s[0] > s[2]) swap();
|
||||
if (s[3] > s[5]) swap();
|
||||
....
|
||||
```
|
||||
|
||||
For instance, when sorting 7 elements, start from `a[a[7]]` (39) until
|
||||
`a[a[8]]` (55), or 16 elements starting at `a[39]`.
|
||||
|
||||
[1]: https://en.wikipedia.org/wiki/Sorting_network
|
||||
|
||||
|
||||
## The Array a[] Explained, Finally ##
|
||||
|
||||
The first set of 9 numbers are both the lengths AND the start and end indexes
|
||||
into the array `a[]`, as explained above in the Network Sort. The second set
|
||||
of numbers runs from indexes 9 through 54, and are the Network Sort comparison
|
||||
values. At index 55 begins the third part of the array. The final 26 values
|
||||
encode the inverse frequency of letters in the English language. The first
|
||||
value is 25 for the letter 'a'. If you count, then 26 is for the letter 'e',
|
||||
the most common letter in the English language
|
||||
(or at least for the dictionary used).
|
||||
|
||||
This final set of letters is used in the routine `l()`. Notice the expression:
|
||||
`a[f[j] + a[~-9]]`; `a[~-9]` is an obscure way of writing `a[8]`, which is the
|
||||
value 55. So `a[f[j]]` is an index into this frequency array, offset by 55.
|
||||
Why is there a `<< 5`? Again, the letter offsets are in the lowest 5 bits,
|
||||
and the counts of the letters is in the upper bits.
|
||||
|
||||
The reason for putting the counts in the upper bits is simple: it makes the
|
||||
value larger for larger counts. Thus, sorting based upon frequency is natural.
|
||||
|
||||
|
||||
## Merge Sort ##
|
||||
|
||||
The network sort as implemented handles up to 7 letters in 3 calls.
|
||||
26 / 7 = 3 r 5. Thus, we need to merge up to 4 sets of 7 letters.
|
||||
This merge is handled by `v()`, which calls `o()` 3 times, once recursively.
|
||||
This is followed by a rearrangement handled in `l()`. This last step finds
|
||||
all the letters with the same frequency, then sorts them according to their
|
||||
English frequency.
|
||||
|
||||
Back to the merge sort, which is really handled in `o()`. This is rather
|
||||
difficult to follow. The first call to `o()` is within the argument list
|
||||
to the second call. The first call has arguments
|
||||
W=0, O=1, R=0, D=a, L=w, E=k; and `v()` was called with `v(l=7, w=b, k=c)`.
|
||||
This first merge pass copies to: `L[R]` (`b[0]`) and selects from either
|
||||
`c[o]` or `c[w]` depending upon which is greater or equal. That is, it merges
|
||||
two 7 letter arrays into a single 14 element array twice, then it merges two 14
|
||||
element arrays into a single 28 element array. Note on the third call
|
||||
to `o()`, the last two arguments are swapped, which puts the final sort
|
||||
into `c[]`.
|
||||
|
||||
Below is a hopefully easier way to read the merge sort code:
|
||||
|
||||
``` <!---c-->
|
||||
// merge residual
|
||||
int e(int mult_o, int start, int to, int off, int *a1, int *a2)
|
||||
{
|
||||
for (; start < off; )
|
||||
a1[to++] = a2[start++ + off * mult_o];
|
||||
return to;
|
||||
}
|
||||
|
||||
// merge sort
|
||||
int o(int mult_o, int mult_w, int to, int len, int *a1, int *a2)
|
||||
{
|
||||
// first call: mult_o = 0, mult_w = 1, to = 0, len = 7, a1=b, a2=c
|
||||
// second: mult_o = 2, mult_w = 3, to = N, len = 7, a1=b, a2=c
|
||||
// third: mult_o = 0, mult_w = 1, to = 0, len = 14, a1=c, a2=b
|
||||
|
||||
int o = 0, w = 0;
|
||||
for (; o < len && w < len; ) {
|
||||
|
||||
// first call: to=0, len=7, mult_o=0, mult_w=1
|
||||
// a1[0++] = a2[0 + 7*0] >= a2[0 + 7*1]
|
||||
// ? a2[0 + 7*0] : a2[0 + 7*1]
|
||||
// a1[0++] = a2[0] > a2[7] ? a[0++] : a2[7++]
|
||||
|
||||
// second call: to=14, len=7, mult_o=2, mult_w=3
|
||||
// a1[14++] = a2[0 + 7*2] >= a2[0 + 7*3]
|
||||
// ? a2[0 + 7*2] : a2[0 + 7*3]
|
||||
// a1[14++] = a2[14] > a2[21] ? a2[14++] : a2[21++]
|
||||
|
||||
// third call: to=0, len=14, mult_o=0, mult_w=1
|
||||
// a1[0++] = a2[0 + 14*0] >= a2[0 + 14*1]
|
||||
// ? a2[0 + 14*0] : a2[0 + 14*1];
|
||||
// a1[0++] = a[0] >= a2[14] ? a2[0++] : a2[14++]
|
||||
|
||||
a1[to++] = a2[o + len * mult_o] >= a2[w + len * mult_w]
|
||||
? a2[o++ + len * mult_o]
|
||||
: a2[w++ + len * mult_w]
|
||||
}
|
||||
int n = e(mult_o, o, to, len, a1, a2);
|
||||
return e(mult_w, w, n, len, a1, a2);
|
||||
}
|
||||
```
|
||||
|
||||
Isn't that as clear as mud? It is far easier to understand the flow when
|
||||
you add `printf()` statements to follow the logic. Included is the file
|
||||
`deobfuscated.c` for you to start with.
|
||||
|
||||
|
||||
## Why name the functions as they are? ##
|
||||
|
||||
Run `make spoiler`.
|
||||
|
||||
|
||||
## Bug Explained ##
|
||||
|
||||
If you followed the above explanation, you will notice that only the first
|
||||
21 of 26 letters are sorted (ignoring { v, w, x, y, z }. But 28 of 26 letters
|
||||
are merge sorted. It was observed the program performs worse if all 26 letters
|
||||
are sorted (which tends to over-favor `y`).
|
||||
But some words do have `y` in them, which is why the merge sort takes 28
|
||||
letters (including the ASCII values `{` and `|`), so all letters are still
|
||||
selected when appropriate. The merge sort puts the { v, w, x, y, z }
|
||||
letters into the proper frequency set, eventually.
|
||||
|
||||
If you change the loop value `22` to `32`, then all letters are sorted,
|
||||
the program will work correctly, but it will change the performance
|
||||
of the algorithm to be slightly worse than the original.
|
||||
|
||||
If you change any values in the array `a[]`,
|
||||
the program will no longer work correctly.
|
||||
|
||||
Finally, what is the significance of the array size 78557?
|
||||
`usdw` only needs 8506. Why was such a large value used?
|
||||
+2315
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* usage: dups [-n] [len]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
int no = ac > 1 && av[1][0] == '-' && av[1][1] == 'n' && ++av && --ac;
|
||||
int n = ac > 1 ? atoi(av[1]) : 5;
|
||||
|
||||
while (fgets(buf, sizeof buf, stdin)) {
|
||||
char d[256] = {0};
|
||||
int skip = 0;
|
||||
if (buf[n] != '\n')
|
||||
continue;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
int c = buf[i] |= 32;
|
||||
if (++d[c] > 1)
|
||||
++skip;
|
||||
}
|
||||
if (!!skip != no)
|
||||
printf("%s", buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# amount of parallelism
|
||||
p=8
|
||||
|
||||
dir=$1
|
||||
: ${dir:=results}
|
||||
mkdir -p $dir
|
||||
|
||||
start_words=$2
|
||||
: ${start_words:=start_words}
|
||||
|
||||
dict=$3
|
||||
: ${dict:=dict}
|
||||
|
||||
rm -fr ./tmp
|
||||
mkdir -p tmp
|
||||
|
||||
# split dict into smaller chucks for some parallelism
|
||||
n=1
|
||||
cat $start_words | ./dups -n | while read a; do
|
||||
echo $a >> tmp/$n
|
||||
((n+=1))
|
||||
test $n -gt $p && n=1
|
||||
done
|
||||
|
||||
# run the experiment (expensive)
|
||||
n=1
|
||||
while test $n -le $p; do
|
||||
./word.result $dir $dict < tmp/$n 2>/dev/null &
|
||||
((n+=1))
|
||||
done
|
||||
|
||||
rm -fr ./tmp
|
||||
|
||||
wait
|
||||
@@ -0,0 +1,887 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<!-- START: two lines up starts content from: inc/top.default.html -->
|
||||
|
||||
<!-- END: this line ends content from: inc/top.default.html -->
|
||||
<!-- START: this line starts content from: inc/head.default.html -->
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../ioccc.css">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@100..900&display=swap" rel="stylesheet">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
<title>The International Obfuscated C Code Contest</title>
|
||||
<link rel="icon" type="image/x-icon" href="../../favicon.ico">
|
||||
<meta name="description" content="extra.md for 2024/burton">
|
||||
<meta name="keywords" content="IOCCC, 2024/burton, extra.md">
|
||||
</head>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
|
||||
<!-- END: this line ends content from: inc/head.default.html -->
|
||||
|
||||
<!-- -->
|
||||
<!-- This web page was formed via the tool: bin/gen-other-html.sh -->
|
||||
<!-- The content of main section of this web page came from: 2024/burton/extra.md -->
|
||||
<!-- -->
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<!-- !!! Do not modify this web page, instead modify the file: 2024/burton/extra.md !!! -->
|
||||
<!-- !!! Do not modify this web page, instead modify the file: 2024/burton/extra.md !!! -->
|
||||
<!-- !!! Do not modify this web page, instead modify the file: 2024/burton/extra.md !!! -->
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
|
||||
<!-- Markdown content was converted into HTML via the tool: bin/md2html.sh -->
|
||||
|
||||
<!-- START: this line starts content from: inc/body.default.html -->
|
||||
|
||||
<body>
|
||||
|
||||
<!-- END: this line ends content from: inc/body.default.html -->
|
||||
<!-- START: this line starts content from: inc/topbar.default.html -->
|
||||
|
||||
<div class="theader">
|
||||
<nav class="topbar">
|
||||
<div class="container">
|
||||
<div class="logo">
|
||||
<a href="../../index.html" class="logo-link">
|
||||
IOCCC
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="topbar-items">
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
Entries
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../years.html" class="sub-item-link">
|
||||
Winning entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../authors.html" class="sub-item-link">
|
||||
Winning authors
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../location.html" class="sub-item-link">
|
||||
Location of authors
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../bugs.html" class="sub-item-link">
|
||||
Bugs and (mis)features
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#fix_an_entry" class="sub-item-link">
|
||||
Fixing entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#fix_author" class="sub-item-link">
|
||||
Updating author info
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
Status
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../news.html" class="sub-item-link">
|
||||
News
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../status.html" class="sub-item-link">
|
||||
Contest status
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../next/rules.html" class="sub-item-link">
|
||||
IOCCC rules
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../next/guidelines.html" class="sub-item-link">
|
||||
IOCCC guidelines
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../markdown.html" class="sub-item-link">
|
||||
Markdown guidelines
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../SECURITY.html" class="sub-item-link">
|
||||
Security policy
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
FAQ
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html" class="sub-item-link">
|
||||
Frequently asked questions
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../quick-start.html#enter" class="sub-item-link">
|
||||
Enter the IOCCC
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#compiling" class="sub-item-link">
|
||||
Compiling entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#running_entries" class="sub-item-link">
|
||||
Running entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#help" class="sub-item-link">
|
||||
How to help
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
About
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../index.html" class="sub-item-link">
|
||||
Home page
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../social.html" class="sub-item-link">
|
||||
IOCCC social media
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../about.html" class="sub-item-link">
|
||||
About the IOCCC
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../judges.html" class="sub-item-link">
|
||||
The judges
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../thanks-for-help.html" class="sub-item-link">
|
||||
Thanks for the help
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../contact.html" class="sub-item-link">
|
||||
Contact us
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="header-mobile-menu">
|
||||
<noscript>
|
||||
<a href="../../nojs-menu.html" class="topbar-js-label">
|
||||
Please Enable JavaScript
|
||||
</a>
|
||||
</noscript>
|
||||
|
||||
<button id="header-open-menu-button" class="topbar-mobile-menu">
|
||||
<img
|
||||
src="../../png/hamburger-icon-open.png"
|
||||
alt="hamburger style menu icon - open state"
|
||||
width=48
|
||||
height=48>
|
||||
</button>
|
||||
|
||||
<button id="header-close-menu-button" class="hide-content">
|
||||
<img
|
||||
src="../../png/hamburger-icon-closed.png"
|
||||
alt="hamburger style menu icon - closed state"
|
||||
width=48
|
||||
height=48>
|
||||
</button>
|
||||
|
||||
<div id="mobile-menu-panel" class="hide-content">
|
||||
<div class="mobile-menu-container">
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
<div class="mobile-menu-item">
|
||||
Entries
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../years.html">
|
||||
Winning entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../authors.html">
|
||||
Winning authors
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../location.html">
|
||||
Location of authors
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../bugs.html">
|
||||
Bugs and (mis)features
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#fix_an_entry">
|
||||
Fixing entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#fix_author">
|
||||
Updating author info
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../thanks-for-help.html">
|
||||
Thanks for the help
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
|
||||
<div class="mobile-menu-item">
|
||||
Status
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../news.html">
|
||||
News
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../status.html">
|
||||
Contest status
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../next/rules.html">
|
||||
IOCCC rules
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../next/guidelines.html">
|
||||
IOCCC guidelines
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../markdown.html">
|
||||
Markdown guidelines
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../SECURITY.html">
|
||||
Security policy
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
<div class="mobile-menu-item">
|
||||
FAQ
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html">
|
||||
Frequently asked questions
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../quick-start.html#enter">
|
||||
Enter the IOCCC
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#compiling">
|
||||
Compiling entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#running_entries">
|
||||
Running entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#help">
|
||||
How to help
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
<div class="mobile-menu-item">
|
||||
About
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../index.html">
|
||||
Home page
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../social.html">
|
||||
IOCCC social media
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../about.html">
|
||||
About the IOCCC
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../judges.html">
|
||||
The judges
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../contact.html">
|
||||
Contact us
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var headerOpenMenuButton = document.getElementById("header-open-menu-button");
|
||||
var headerCloseMenuButton = document.getElementById("header-close-menu-button");
|
||||
var mobileMenuPanel = document.getElementById("mobile-menu-panel");
|
||||
|
||||
headerOpenMenuButton.addEventListener("click", () => {
|
||||
headerOpenMenuButton.classList.remove("topbar-mobile-menu");
|
||||
headerOpenMenuButton.classList.add("hide-content");
|
||||
|
||||
headerCloseMenuButton.classList.remove("hide-content");
|
||||
headerCloseMenuButton.classList.add("topbar-mobile-menu");
|
||||
|
||||
mobileMenuPanel.classList.remove("hide-content");
|
||||
mobileMenuPanel.classList.add("topbar-mobile-panel");
|
||||
});
|
||||
|
||||
headerCloseMenuButton.addEventListener("click", () => {
|
||||
headerCloseMenuButton.classList.remove("topbar-mobile-menu");
|
||||
headerCloseMenuButton.classList.add("hide-content");
|
||||
|
||||
mobileMenuPanel.classList.add("hide-content");
|
||||
mobileMenuPanel.classList.remove("topbar-mobile-panel");
|
||||
|
||||
headerOpenMenuButton.classList.add("topbar-mobile-menu");
|
||||
headerOpenMenuButton.classList.remove("hide-content");
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- END: this line ends content from: inc/topbar.default.html -->
|
||||
<!-- START: this line starts content from: inc/header.default.html -->
|
||||
|
||||
<div class="header">
|
||||
<a href="../../2011/zucker/index.html">
|
||||
<img src="../../png/ioccc.png"
|
||||
alt="IOCCC image by Matt Zucker"
|
||||
width=300
|
||||
height=110>
|
||||
</a>
|
||||
<h1>The International Obfuscated C Code Contest</h1>
|
||||
<h2>extra.html for 2024/burton</h2>
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/header.default.html -->
|
||||
<!-- START: this line starts content from: inc/navbar.up2index.html -->
|
||||
|
||||
<div class="navbar">
|
||||
<a class="Left" href="index.html">↑ jump to 2024/burton/index.html ↑</a>
|
||||
<a class="Right" href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fwww.ioccc.org%2F2024%2Fburton%2Fextra.html">✓</a>
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/navbar.up2index.html -->
|
||||
<!-- START: this line starts content from: inc/before-content.default.html -->
|
||||
|
||||
<div class="content" id="content">
|
||||
|
||||
<!-- END: this line ends content from: inc/before-content.default.html -->
|
||||
<!-- START: this line starts content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||||
|
||||
<!-- BEFORE: 1st line of markdown file: 2024/burton/extra.md -->
|
||||
<h1 id="extra">extra</h1>
|
||||
<p>This readme provides a description of the extra files provided, how to use them,
|
||||
analysis of their results, and a deeper investigation on the failed guesses.</p>
|
||||
<p>The recommendation is to do:</p>
|
||||
<pre><code> make tools
|
||||
|
||||
./run dict blast swept # exhaust runs this command a LOT!
|
||||
./run dict crate swept # show the diff between starting words
|
||||
|
||||
mkdir results # create the results directory
|
||||
./exhaust # exhaustive test of all words (~1 hour)
|
||||
echo terns | ./word.result # add the word "terns" to results
|
||||
./mkresults > results.avg # proc exhaust into a single, small file</code></pre>
|
||||
<p>The files created as output from <code>exhaust</code> allow one to view, for each
|
||||
starting word, how each of the solutions resolve, including the misses.
|
||||
<code>mkresults</code> outputs a 1566 line report showing the starting word, its
|
||||
average accuracy, and the number of missed words. To show the number
|
||||
of guesses and the actual missed words, run <code>rank</code> on the desired word:</p>
|
||||
<pre><code> ./rank results/blast
|
||||
|
||||
1 1 # blast guessed itself
|
||||
2 112 # 112 words guessed in 2 attempts
|
||||
3 867 # 867 words guessed in 3 attempts
|
||||
4 1019 # ...
|
||||
5 271
|
||||
6 41
|
||||
foyer jaunt shave wound
|
||||
|
||||
./avg results/blast
|
||||
|
||||
blast 3.673002 4
|
||||
|
||||
grep blast results.avg
|
||||
|
||||
blast 3.673002 4</code></pre>
|
||||
<p>The C programs allow for (automated) testing:</p>
|
||||
<pre><code> gen.c - simulate wordle game by generating targets and scoring guesses
|
||||
./gen dict [target]
|
||||
|
||||
dups.c - remove words with(out) repeated letters
|
||||
(best starting words have no repeats)
|
||||
cat dict | wc -l # all the words
|
||||
cat dict | ./dups | wc -l # words with repeated letters
|
||||
cat dict | ./dups -n | wc -l # words without repeated letters
|
||||
|
||||
run.c - `gen` and `prog` connected via pipes; allows automated testing
|
||||
./run dict [start [target]]
|
||||
start - the first guess
|
||||
target - force the target to be the named word</code></pre>
|
||||
<h2 id="using-more-guesses">Using More Guesses</h2>
|
||||
<p>If you wish to see the failed words in action, and if more guesses would
|
||||
work, try:</p>
|
||||
<pre><code> ./run dict blast jaunt | grep ^gen
|
||||
|
||||
gen: target: jaunt
|
||||
gen: blast bbybg
|
||||
gen: daunt bgggg
|
||||
gen: haunt bgggg
|
||||
gen: gaunt bgggg
|
||||
gen: vaunt bgggg
|
||||
gen: taunt ygggg
|
||||
gen result end=0: n 6 lose: jaunt
|
||||
|
||||
GUESSES=7 ./run dict blast jaunt | grep ^gen
|
||||
|
||||
gen: target: jaunt
|
||||
gen: blast bbybg
|
||||
gen: daunt bgggg
|
||||
gen: haunt bgggg
|
||||
gen: gaunt bgggg
|
||||
gen: vaunt bgggg
|
||||
gen: taunt ygggg
|
||||
gen: jaunt ggggg
|
||||
gen result end=2: y 7 good: jaunt</code></pre>
|
||||
<p>Using <code>GUESSES=9</code> and <code>exhaust</code>, one gets a metric that scores words without
|
||||
misses, allowing a better comparison on the average score. Note, however,
|
||||
that the game doesn’t bend this way, and anything more than 6 guesses is a
|
||||
loss. Take this metric with a grain of salt. Also, 9 is the limit of
|
||||
guesses; the program will not work properly - if at all - with more than
|
||||
9 guesses.</p>
|
||||
<p>Ranking by fewest missed with GUESSES=6, the order is:</p>
|
||||
<pre><code> blast palsy climb flash lapse</code></pre>
|
||||
<p>Ranking by average with GUESSES=6, the order is:</p>
|
||||
<pre><code> crate slate trace crane least</code></pre>
|
||||
<p>Ranking by average with GUESSES=9, the order is:</p>
|
||||
<pre><code> slate trace crate train least</code></pre>
|
||||
<p>To reproduce these results:</p>
|
||||
<pre><code> GUESSES=9 ./exhaust results.9
|
||||
./mkresults results.9 > results.9.avg</code></pre>
|
||||
<h2 id="simple-analysis">Simple Analysis</h2>
|
||||
<p>The 1566 raw files produced by <code>exhaust</code> are ~370KB each (total ~562MB),
|
||||
far too large to submit, so included are the compressed results files for
|
||||
four starting words, and the summary file <code>results.avg</code>.</p>
|
||||
<pre><code> blast fewest missed
|
||||
crate best average
|
||||
query most missing
|
||||
terns example used in remarks</code></pre>
|
||||
<p>The program <code>rank</code> allows one to see how the averages are calculated, as well
|
||||
as the actual missed words. Comparing the results for <code>blast</code> and <code>terns</code>:</p>
|
||||
<pre><code> ./rank r.terns | awk 'NF==2' > a
|
||||
./rank r.blast | awk 'NF==2' > b
|
||||
join a b | column -t
|
||||
|
||||
guesses terns blast
|
||||
-------- ----- -----
|
||||
2 110 112
|
||||
3 909 867
|
||||
4 960 1019
|
||||
5 265 271
|
||||
6 53 41
|
||||
|
||||
F 18 4 (failed puzzles)</code></pre>
|
||||
<p>In general, the program <code>avg</code> is easier to use, but conveys less information:</p>
|
||||
<pre><code> ./avg r.terns; ./avg r.blast
|
||||
terns 3.641469 18
|
||||
blast 3.673002 4</code></pre>
|
||||
<p>You have to decide if you prefer a marginally lower average, but slightly
|
||||
higher chance of losing, versus a marginally higher average and lower chance
|
||||
of losing. This is developed further in the following section.</p>
|
||||
<p>It is interesting that the letter order makes a noticeable difference:</p>
|
||||
<pre><code> ./avg r.terns; ./avg results/stern
|
||||
terns 3.641469 18 # lower average and fewer misses
|
||||
stern 3.658315 20</code></pre>
|
||||
<p>For completeness, using <code>GUESSES=9</code> and the full starting dictionary from
|
||||
Wordle(tm), here are the results for the “best” starting words: <code>salet</code>,
|
||||
<code>slate</code>, and <code>blast</code>.</p>
|
||||
<pre><code> guesses salet slate blast
|
||||
------- ----- ----- -----
|
||||
1 0 1 1
|
||||
2 148 146 112
|
||||
3 932 939 867
|
||||
4 925 919 1019
|
||||
5 240 235 271
|
||||
6 56 57 41
|
||||
--- ----- ----- -----
|
||||
7 11 13 4
|
||||
8 2 4 0
|
||||
9 1 1 0
|
||||
--- ----- ----- -----
|
||||
avg 3.641 3.644 3.685</code></pre>
|
||||
<p>Obviously, <code>salet</code> produces the best results, excepting the losses (14).
|
||||
Just re-arranging the letters into <code>slate</code> produces almost the same,
|
||||
but there are more losses (18). If attempting to minimize losses,
|
||||
then <code>blast</code> is the optimal starting guess, since it never takes more
|
||||
than 7 guesses and has the fewest losses (4) of any starting word in the
|
||||
combined full Wordle(tm) dictionary.</p>
|
||||
<p>NB: The averages for <code>GUESSES=9</code> are larger than the default,
|
||||
because the misses are essentially folded into the average.
|
||||
The averages are more accurately compared when using the higher limit,
|
||||
although minimizing losses remains the priority (who likes to lose?).</p>
|
||||
<h2 id="seek-these">Seek These</h2>
|
||||
<p>The starting words with the fewest misses with <code>dict</code>:</p>
|
||||
<pre><code> sort -k3n results.avg | sed 18q | awk '{print $1, $3}' | column -t | pr -t -3
|
||||
|
||||
blast 4 ralph 7 crawl 8
|
||||
palsy 6 ranch 7 crumb 8
|
||||
climb 7 shawl 7 grasp 8
|
||||
flash 7 tramp 7 lymph 8
|
||||
lapse 7 clash 8 spark 8
|
||||
prowl 7 clasp 8 swamp 8
|
||||
|
||||
The starting words with the best accuracy:
|
||||
|
||||
sort -k2n results.avg | sed 18q | pr -t -3
|
||||
|
||||
crate 3.586609 20 irate 3.611231 31 trice 3.617279 15
|
||||
slate 3.586609 18 slice 3.612095 22 cater 3.620302 26
|
||||
trace 3.588769 18 stale 3.612959 19 satin 3.621598 19
|
||||
crane 3.595248 26 train 3.613391 14 snail 3.621598 19
|
||||
least 3.599568 19 trade 3.613823 20 stare 3.621598 19
|
||||
plate 3.606479 22 leant 3.616415 18 dealt 3.622462 15
|
||||
|
||||
Note the word with fewest misses, `blast`, is relatively far
|
||||
down the list in accuracy at 178th best:
|
||||
|
||||
sort -k2n results.avg | pr -t -n | grep blast
|
||||
|
||||
178 blast 3.673002 4</code></pre>
|
||||
<p>Versus starting words with fewest misses:</p>
|
||||
<pre><code> egrep 'terns|lapse|blast|climb|crate' results.avg
|
||||
|
||||
blast 3.673002 4
|
||||
climb 3.772354 7
|
||||
crate 3.586609 20
|
||||
lapse 3.664795 7
|
||||
terns 3.641469 18
|
||||
|
||||
weighted avg
|
||||
# blast crate blast crate improvement
|
||||
- ----- ----- --------------- -----------
|
||||
1 1 1 1.0000 1.0000 0.0000
|
||||
2 112 147 1.9912 1.9932 -0.0020
|
||||
3 867 952 2.8837 2.8645 -0.0192
|
||||
4 1019 884 3.4527 3.3951 -0.0576
|
||||
5 271 250 3.6374 3.5775 -0.0599
|
||||
6 41 61 3.6794 3.6429 -0.0365
|
||||
|
||||
F 4 20 -16 +16 (0.26% blast vs 1.28% crate)</code></pre>
|
||||
<p>Notice the difference in the average and weighted average. The program
|
||||
<code>avg</code> simply takes the total guesses as a percentage of the total words.
|
||||
The program <code>wavg</code> takes each of the six scores and weights them by the
|
||||
score. I wrote <code>wavg</code> later to track my progress playing the online game,
|
||||
and it is a more accurate score IMHO, but both are useful for comparisons.</p>
|
||||
<pre><code> $ ./avg results/blast
|
||||
blast 3.673002 4
|
||||
$ ./rank results/blast
|
||||
1 1
|
||||
2 112
|
||||
3 867
|
||||
4 1019
|
||||
5 271
|
||||
6 41
|
||||
foyer jaunt shave wound
|
||||
$ ./wavg 1 112 867 1019 271 41
|
||||
3.6794</code></pre>
|
||||
<p>The program <code>wrank</code> (weighted rank) makes this latter calculation much easier.
|
||||
It takes the output from <code>rank</code> and invokes <code>wavg</code> with these numbers,
|
||||
saving a lot of typing and errors.</p>
|
||||
<pre><code> ./wrank blast
|
||||
blast 3.6794</code></pre>
|
||||
<p>In words, <code>crate</code> as a first guess gets more correct answers in 2 and 3
|
||||
guesses, reducing its cost. It looks to be a stronger candidate, but it
|
||||
misses 16 more words (therefore losing the game more often). Your task
|
||||
is to determine your risk profile, and decide among the variety of possible
|
||||
starting points, then let <code>prog</code> recommend your next guess.</p>
|
||||
<p>A somewhat laborious calculation provides the answer to which starting word
|
||||
has the most answers in two words and three words:</p>
|
||||
<pre><code> # two words
|
||||
for n in results/*; do
|
||||
rank $n | awk -v word=$n '/^2/ {print word,$2}';
|
||||
done | sort -k2nr | sed 3q
|
||||
|
||||
trace 149
|
||||
crate 147
|
||||
slate 146
|
||||
|
||||
# three words
|
||||
for n in results/*; do
|
||||
rank $n | awk -v word=$n '/^3/ {print word,$2}';
|
||||
done | sort -k2nr | sed 4q
|
||||
|
||||
crate 952
|
||||
train 944
|
||||
trace 939
|
||||
slate 936
|
||||
|
||||
# versus the averages
|
||||
sort -k2n -k3n results.avg | sed 3q
|
||||
slate 3.586609 18
|
||||
crate 3.586609 20
|
||||
trace 3.588769 18</code></pre>
|
||||
<h2 id="avoid-these">Avoid These</h2>
|
||||
<p>The starting words with the worst accuracy:</p>
|
||||
<pre><code> sort -k2nr results.avg | sed 18q | pr -t -3
|
||||
|
||||
jumpy 3.997408 21 juicy 3.954212 39 squib 3.927862 28
|
||||
jumbo 3.996976 25 quake 3.952052 38 quark 3.926566 30
|
||||
buxom 3.995248 23 jerky 3.950756 31 quoth 3.920950 33
|
||||
quick 3.987041 36 equip 3.939957 22 gawky 3.918790 22
|
||||
quack 3.974514 23 quasi 3.938661 32 unzip 3.915335 24
|
||||
quirk 3.964147 40 epoxy 3.934773 27 judge 3.914903 33</code></pre>
|
||||
<p>The starting words with the most failures (missed words):</p>
|
||||
<pre><code> sort -k3nr results.avg | sed 18q | pr -t -3
|
||||
|
||||
query 3.893305 43 juicy 3.954212 39 enjoy 3.890713 37
|
||||
quite 3.835421 42 quota 3.881641 39 gauze 3.878186 37
|
||||
yield 3.740821 41 quake 3.952052 38 oxide 3.888121 37
|
||||
juice 3.847084 40 quiet 3.857451 38 fiery 3.772786 36
|
||||
quirk 3.964147 40 quote 3.829374 38 quail 3.893737 36
|
||||
axion 3.796544 39 unify 3.862203 38 quick 3.987041 36</code></pre>
|
||||
<p>The worst target words, for any starting word (N out of 1566):</p>
|
||||
<pre><code> ./worst
|
||||
|
||||
wound 1340 jaunt 1254 hatch 1157 foyer 1109 waste 1057
|
||||
found 997 shave 945 wight 943 willy 790 catch 779
|
||||
boxer 762 jolly 751 graze 626 rower 611 fatty 598
|
||||
roger 568 taunt 520 watch 497 witty 483 wooer 451
|
||||
tight 449 bound 442 swore 415 taste 405 mower 378
|
||||
hover 374 bunch 371 shake 358 racer 348 rarer 294
|
||||
paper 289 water 285 stave 271 ferry 250 fever 242
|
||||
fully 241 paddy 239 fight 225 parer 219 taffy 207
|
||||
frown 196 joker 195 filly 188 batty 179 lowly 179
|
||||
staff 176 jazzy 174 piper 152 vying 152 swear 151</code></pre>
|
||||
<h2 id="spoiler-deep-dive-on-near-misses-spoiler">SPOILER Deep Dive on Near Misses SPOILER</h2>
|
||||
<p>Dissecting the failed targets when starting with <code>blast</code>. Recall <code>blast</code>
|
||||
only misses 4 words out of all 2315:</p>
|
||||
<pre><code> foyer jaunt shave wound</code></pre>
|
||||
<p>These four words have common sub-patterns, which in hard-mode is difficult
|
||||
to disambiguate. Using <code>run dict blast $word</code>, here are the grep sub-patterns
|
||||
and counts for these four words as revealed in the output:</p>
|
||||
<pre><code> foyer 25 grep '^.o.er' dict | wc -l
|
||||
jaunt 6 grep '^.aunt' dict | wc -l
|
||||
shave 7 grep '^sha.e' dict | wc -l
|
||||
wound 8 grep '^.ound' dict | wc -l</code></pre>
|
||||
<p>Looking at the patterns, the program is making guesses that just happen to
|
||||
select the correct word last in its choices. In all cases, on the seventh
|
||||
guess, the program has the correct answer using <code>blast</code> as the starting guess.
|
||||
It is easy to do an exhaustive look for only four words, but as the count
|
||||
goes up, so does the work.</p>
|
||||
<p>Several variations were attempted, including randomization of the few results
|
||||
remaining. Besides being non-deterministic (this time it wins, next time it
|
||||
loses), better results were obtained with other changes to the selection
|
||||
algorithm. Some small insight into the algorithm used may be seen by the
|
||||
<code>grep</code> command lines, although there are additional insights used within
|
||||
the program that improve significantly upon these results.</p>
|
||||
<pre><code> ./run dict blast foyer | grep ^gen
|
||||
gen: target: foyer 2315
|
||||
gen: blast bbbbb 429 grep -v '[blast]' dict | wc -l
|
||||
gen: drone byyby 27 grep r dict | grep o | grep e | grep -v '[blastdn]' | wc -l
|
||||
gen: cower bgbgg 8 grep '^.o.er' dict | grep -v '[blastdncw]'
|
||||
foyer homer hover joker
|
||||
mover poker roger rover
|
||||
gen: mover bgbgg 4 grep '.o.er' dict | grep -v '[blastdncwmv]'
|
||||
foyer joker poker roger
|
||||
gen: poker bgbgg rm poker joker (foyer roger)
|
||||
gen: roger ygbgg rm roger (foyer)
|
||||
gen result end=0: n 6 lose: foyer
|
||||
|
||||
---------------
|
||||
|
||||
./run dict blast jaunt | grep ^gen
|
||||
gen: target: jaunt 2315
|
||||
gen: blast bbybg 46 grep 't$' dict | grep a | grep -v '[bls]' | wc -l
|
||||
gen: daunt bgggg 5 grep '^.aunt$' dict | grep -v '[blsd]'
|
||||
gaunt haunt jaunt taunt
|
||||
vaunt
|
||||
gen: haunt bgggg rm haunt (gaunt, jaunt, taunt, vaunt)
|
||||
gen: gaunt bgggg rm guant (jaunt, taunt, vaunt)
|
||||
gen: vaunt bgggg rm vaunt (jaunt, taunt)
|
||||
gen: taunt ygggg rm taunt (jaunt)
|
||||
gen result end=0: n 6 lose: jaunt
|
||||
|
||||
---------------
|
||||
|
||||
./run dict blast shave | grep ^gen
|
||||
gen: target: shake 2315
|
||||
gen: blast bbgyb 52 grep '^..a' dict | grep s | grep -v '[blt]' | wc -l
|
||||
gen: share gggbg 5 grep '^sha.e' dict | grep -v '[bltr]'
|
||||
shade shake shame shape
|
||||
shave
|
||||
gen: shade gggbg rm shade (shake shame shape shave)
|
||||
gen: shape gggbg rm shape (shake shame shave)
|
||||
gen: shame gggbg rm shame (shake shave)
|
||||
gen: shake gggbg rm shake (shave)
|
||||
gen result end=0: n 6 lose: shave
|
||||
|
||||
---------------
|
||||
|
||||
./run dict blast wound | grep ^gen
|
||||
gen: target: wound 2315
|
||||
gen: blast bbbbb 429 grep -v '[blast]' dict | wc -l
|
||||
gen: drone ybygb 7 grep 'n.$' dict | grep d | grep o | grep -v '[blastre]' | wc -l
|
||||
gen: pound bgggg 4 grep '^.ound' dict | grep -v '[blastreh]'
|
||||
found hound mound wound
|
||||
gen: mound bgggg rm mound (found, hound, wound)
|
||||
gen: hound bgggg rm hound (found, wound)
|
||||
gen: found bgggg rm found (wound)
|
||||
gen result end=0: n 6 lose: wound</code></pre>
|
||||
<!-- AFTER: last line of markdown file: 2024/burton/extra.md -->
|
||||
|
||||
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||||
<!-- START: this line starts content from: inc/after-content.default.html -->
|
||||
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/after-content.default.html -->
|
||||
<!-- START: this line starts content from: inc/footer.default.html -->
|
||||
|
||||
<!--
|
||||
|
||||
Copyright © 1984-2025 by Landon Curt Noll. All Rights Reserved.
|
||||
|
||||
You are free to share and adapt this file under the terms of this license:
|
||||
|
||||
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
||||
|
||||
For more information, see:
|
||||
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
-->
|
||||
|
||||
<div class="footer">
|
||||
|
||||
<div id="copyright"><h3>Copyright © 1984-2025 by Landon Curt Noll:
|
||||
<a href="https://creativecommons.org/faq/#what-does-some-rights-reserved-mean"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer">Some Rights Reserved</a></h3>
|
||||
<p>
|
||||
This work is <b>licensed by Landon Curt Noll</b> under
|
||||
<b><a href="https://creativecommons.org/licenses/by-sa/4.0/?ref=chooser-v1"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer"
|
||||
style="display:inline-block;">CC BY-SA 4.0</a></b>.
|
||||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||||
src="../../png/cc.png"
|
||||
alt="cc inside circle symbol">
|
||||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||||
src="../../png/by.png"
|
||||
alt="person inside circle symbol">
|
||||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||||
src="../../png/sa.png"
|
||||
alt="arrow looping back on itself inside circle symbol"><br>
|
||||
You should <b>carefully review</b> the
|
||||
<b><a href="https://creativecommons.org/licenses/by-sa/4.0/legalcode.en"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer">CC BY-SA 4.0 LEGAL CODE</a></b>
|
||||
before using the licensed material.<br>
|
||||
You may wish to review the
|
||||
<b><a href="../../license.html"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer">highlights of some of the key features and terms</a></b>
|
||||
of <b>CC BY-SA 4.0</b>.<br>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="coda"><h3>Coda</h3>
|
||||
<p>
|
||||
<a href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fwww.ioccc.org%2F2024%2Fburton%2Fextra.html" rel="nofollow">Nu HTML check this web page</a><br>
|
||||
<a href="#top">Jump to top</a> <a href="#content">Jump to Content</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/footer.default.html -->
|
||||
<!-- START: this line starts content from: inc/bottom.default.html -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<!-- END: this line ends content from: inc/bottom.default.html -->
|
||||
@@ -0,0 +1,471 @@
|
||||
# extra
|
||||
|
||||
This readme provides a description of the extra files provided, how to use them,
|
||||
analysis of their results, and a deeper investigation on the failed guesses.
|
||||
|
||||
The recommendation is to do:
|
||||
|
||||
``` <!---sh-->
|
||||
make tools
|
||||
|
||||
./run dict blast swept # exhaust runs this command a LOT!
|
||||
./run dict crate swept # show the diff between starting words
|
||||
|
||||
mkdir results # create the results directory
|
||||
./exhaust # exhaustive test of all words (~1 hour)
|
||||
echo terns | ./word.result # add the word "terns" to results
|
||||
./mkresults > results.avg # proc exhaust into a single, small file
|
||||
```
|
||||
|
||||
The files created as output from `exhaust` allow one to view, for each
|
||||
starting word, how each of the solutions resolve, including the misses.
|
||||
`mkresults` outputs a 1566 line report showing the starting word, its
|
||||
average accuracy, and the number of missed words. To show the number
|
||||
of guesses and the actual missed words, run `rank` on the desired word:
|
||||
|
||||
``` <!---sh-->
|
||||
./rank results/blast
|
||||
|
||||
1 1 # blast guessed itself
|
||||
2 112 # 112 words guessed in 2 attempts
|
||||
3 867 # 867 words guessed in 3 attempts
|
||||
4 1019 # ...
|
||||
5 271
|
||||
6 41
|
||||
foyer jaunt shave wound
|
||||
|
||||
./avg results/blast
|
||||
|
||||
blast 3.673002 4
|
||||
|
||||
grep blast results.avg
|
||||
|
||||
blast 3.673002 4
|
||||
```
|
||||
|
||||
The C programs allow for (automated) testing:
|
||||
|
||||
```
|
||||
gen.c - simulate wordle game by generating targets and scoring guesses
|
||||
./gen dict [target]
|
||||
|
||||
dups.c - remove words with(out) repeated letters
|
||||
(best starting words have no repeats)
|
||||
cat dict | wc -l # all the words
|
||||
cat dict | ./dups | wc -l # words with repeated letters
|
||||
cat dict | ./dups -n | wc -l # words without repeated letters
|
||||
|
||||
run.c - `gen` and `prog` connected via pipes; allows automated testing
|
||||
./run dict [start [target]]
|
||||
start - the first guess
|
||||
target - force the target to be the named word
|
||||
```
|
||||
|
||||
|
||||
## Using More Guesses
|
||||
|
||||
If you wish to see the failed words in action, and if more guesses would
|
||||
work, try:
|
||||
|
||||
```
|
||||
./run dict blast jaunt | grep ^gen
|
||||
|
||||
gen: target: jaunt
|
||||
gen: blast bbybg
|
||||
gen: daunt bgggg
|
||||
gen: haunt bgggg
|
||||
gen: gaunt bgggg
|
||||
gen: vaunt bgggg
|
||||
gen: taunt ygggg
|
||||
gen result end=0: n 6 lose: jaunt
|
||||
|
||||
GUESSES=7 ./run dict blast jaunt | grep ^gen
|
||||
|
||||
gen: target: jaunt
|
||||
gen: blast bbybg
|
||||
gen: daunt bgggg
|
||||
gen: haunt bgggg
|
||||
gen: gaunt bgggg
|
||||
gen: vaunt bgggg
|
||||
gen: taunt ygggg
|
||||
gen: jaunt ggggg
|
||||
gen result end=2: y 7 good: jaunt
|
||||
```
|
||||
|
||||
Using `GUESSES=9` and `exhaust`, one gets a metric that scores words without
|
||||
misses, allowing a better comparison on the average score. Note, however,
|
||||
that the game doesn't bend this way, and anything more than 6 guesses is a
|
||||
loss. Take this metric with a grain of salt. Also, 9 is the limit of
|
||||
guesses; the program will not work properly - if at all - with more than
|
||||
9 guesses.
|
||||
|
||||
Ranking by fewest missed with GUESSES=6, the order is:
|
||||
|
||||
```
|
||||
blast palsy climb flash lapse
|
||||
```
|
||||
|
||||
Ranking by average with GUESSES=6, the order is:
|
||||
|
||||
```
|
||||
crate slate trace crane least
|
||||
```
|
||||
|
||||
Ranking by average with GUESSES=9, the order is:
|
||||
|
||||
```
|
||||
slate trace crate train least
|
||||
```
|
||||
|
||||
To reproduce these results:
|
||||
|
||||
```
|
||||
GUESSES=9 ./exhaust results.9
|
||||
./mkresults results.9 > results.9.avg
|
||||
```
|
||||
|
||||
|
||||
## Simple Analysis
|
||||
|
||||
The 1566 raw files produced by `exhaust` are ~370KB each (total ~562MB),
|
||||
far too large to submit, so included are the compressed results files for
|
||||
four starting words, and the summary file `results.avg`.
|
||||
|
||||
```
|
||||
blast fewest missed
|
||||
crate best average
|
||||
query most missing
|
||||
terns example used in remarks
|
||||
```
|
||||
|
||||
The program `rank` allows one to see how the averages are calculated, as well
|
||||
as the actual missed words. Comparing the results for `blast` and `terns`:
|
||||
|
||||
```
|
||||
./rank r.terns | awk 'NF==2' > a
|
||||
./rank r.blast | awk 'NF==2' > b
|
||||
join a b | column -t
|
||||
|
||||
guesses terns blast
|
||||
-------- ----- -----
|
||||
2 110 112
|
||||
3 909 867
|
||||
4 960 1019
|
||||
5 265 271
|
||||
6 53 41
|
||||
|
||||
F 18 4 (failed puzzles)
|
||||
```
|
||||
|
||||
In general, the program `avg` is easier to use, but conveys less information:
|
||||
|
||||
```
|
||||
./avg r.terns; ./avg r.blast
|
||||
terns 3.641469 18
|
||||
blast 3.673002 4
|
||||
```
|
||||
|
||||
You have to decide if you prefer a marginally lower average, but slightly
|
||||
higher chance of losing, versus a marginally higher average and lower chance
|
||||
of losing. This is developed further in the following section.
|
||||
|
||||
It is interesting that the letter order makes a noticeable difference:
|
||||
|
||||
```
|
||||
./avg r.terns; ./avg results/stern
|
||||
terns 3.641469 18 # lower average and fewer misses
|
||||
stern 3.658315 20
|
||||
```
|
||||
|
||||
For completeness, using `GUESSES=9` and the full starting dictionary from
|
||||
Wordle(tm), here are the results for the "best" starting words: `salet`,
|
||||
`slate`, and `blast`.
|
||||
|
||||
```
|
||||
guesses salet slate blast
|
||||
------- ----- ----- -----
|
||||
1 0 1 1
|
||||
2 148 146 112
|
||||
3 932 939 867
|
||||
4 925 919 1019
|
||||
5 240 235 271
|
||||
6 56 57 41
|
||||
--- ----- ----- -----
|
||||
7 11 13 4
|
||||
8 2 4 0
|
||||
9 1 1 0
|
||||
--- ----- ----- -----
|
||||
avg 3.641 3.644 3.685
|
||||
```
|
||||
|
||||
Obviously, `salet` produces the best results, excepting the losses (14).
|
||||
Just re-arranging the letters into `slate` produces almost the same,
|
||||
but there are more losses (18). If attempting to minimize losses,
|
||||
then `blast` is the optimal starting guess, since it never takes more
|
||||
than 7 guesses and has the fewest losses (4) of any starting word in the
|
||||
combined full Wordle(tm) dictionary.
|
||||
|
||||
NB: The averages for `GUESSES=9` are larger than the default,
|
||||
because the misses are essentially folded into the average.
|
||||
The averages are more accurately compared when using the higher limit,
|
||||
although minimizing losses remains the priority (who likes to lose?).
|
||||
|
||||
|
||||
## Seek These
|
||||
|
||||
The starting words with the fewest misses with `dict`:
|
||||
|
||||
```
|
||||
sort -k3n results.avg | sed 18q | awk '{print $1, $3}' | column -t | pr -t -3
|
||||
|
||||
blast 4 ralph 7 crawl 8
|
||||
palsy 6 ranch 7 crumb 8
|
||||
climb 7 shawl 7 grasp 8
|
||||
flash 7 tramp 7 lymph 8
|
||||
lapse 7 clash 8 spark 8
|
||||
prowl 7 clasp 8 swamp 8
|
||||
|
||||
The starting words with the best accuracy:
|
||||
|
||||
sort -k2n results.avg | sed 18q | pr -t -3
|
||||
|
||||
crate 3.586609 20 irate 3.611231 31 trice 3.617279 15
|
||||
slate 3.586609 18 slice 3.612095 22 cater 3.620302 26
|
||||
trace 3.588769 18 stale 3.612959 19 satin 3.621598 19
|
||||
crane 3.595248 26 train 3.613391 14 snail 3.621598 19
|
||||
least 3.599568 19 trade 3.613823 20 stare 3.621598 19
|
||||
plate 3.606479 22 leant 3.616415 18 dealt 3.622462 15
|
||||
|
||||
Note the word with fewest misses, `blast`, is relatively far
|
||||
down the list in accuracy at 178th best:
|
||||
|
||||
sort -k2n results.avg | pr -t -n | grep blast
|
||||
|
||||
178 blast 3.673002 4
|
||||
```
|
||||
|
||||
Versus starting words with fewest misses:
|
||||
|
||||
```
|
||||
egrep 'terns|lapse|blast|climb|crate' results.avg
|
||||
|
||||
blast 3.673002 4
|
||||
climb 3.772354 7
|
||||
crate 3.586609 20
|
||||
lapse 3.664795 7
|
||||
terns 3.641469 18
|
||||
|
||||
weighted avg
|
||||
# blast crate blast crate improvement
|
||||
- ----- ----- --------------- -----------
|
||||
1 1 1 1.0000 1.0000 0.0000
|
||||
2 112 147 1.9912 1.9932 -0.0020
|
||||
3 867 952 2.8837 2.8645 -0.0192
|
||||
4 1019 884 3.4527 3.3951 -0.0576
|
||||
5 271 250 3.6374 3.5775 -0.0599
|
||||
6 41 61 3.6794 3.6429 -0.0365
|
||||
|
||||
F 4 20 -16 +16 (0.26% blast vs 1.28% crate)
|
||||
```
|
||||
|
||||
Notice the difference in the average and weighted average. The program
|
||||
`avg` simply takes the total guesses as a percentage of the total words.
|
||||
The program `wavg` takes each of the six scores and weights them by the
|
||||
score. I wrote `wavg` later to track my progress playing the online game,
|
||||
and it is a more accurate score IMHO, but both are useful for comparisons.
|
||||
|
||||
``` <!---sh-->
|
||||
$ ./avg results/blast
|
||||
blast 3.673002 4
|
||||
$ ./rank results/blast
|
||||
1 1
|
||||
2 112
|
||||
3 867
|
||||
4 1019
|
||||
5 271
|
||||
6 41
|
||||
foyer jaunt shave wound
|
||||
$ ./wavg 1 112 867 1019 271 41
|
||||
3.6794
|
||||
```
|
||||
|
||||
The program `wrank` (weighted rank) makes this latter calculation much easier.
|
||||
It takes the output from `rank` and invokes `wavg` with these numbers,
|
||||
saving a lot of typing and errors.
|
||||
|
||||
``` <!---sh-->
|
||||
./wrank blast
|
||||
blast 3.6794
|
||||
```
|
||||
|
||||
In words, `crate` as a first guess gets more correct answers in 2 and 3
|
||||
guesses, reducing its cost. It looks to be a stronger candidate, but it
|
||||
misses 16 more words (therefore losing the game more often). Your task
|
||||
is to determine your risk profile, and decide among the variety of possible
|
||||
starting points, then let `prog` recommend your next guess.
|
||||
|
||||
A somewhat laborious calculation provides the answer to which starting word
|
||||
has the most answers in two words and three words:
|
||||
|
||||
```
|
||||
# two words
|
||||
for n in results/*; do
|
||||
rank $n | awk -v word=$n '/^2/ {print word,$2}';
|
||||
done | sort -k2nr | sed 3q
|
||||
|
||||
trace 149
|
||||
crate 147
|
||||
slate 146
|
||||
|
||||
# three words
|
||||
for n in results/*; do
|
||||
rank $n | awk -v word=$n '/^3/ {print word,$2}';
|
||||
done | sort -k2nr | sed 4q
|
||||
|
||||
crate 952
|
||||
train 944
|
||||
trace 939
|
||||
slate 936
|
||||
|
||||
# versus the averages
|
||||
sort -k2n -k3n results.avg | sed 3q
|
||||
slate 3.586609 18
|
||||
crate 3.586609 20
|
||||
trace 3.588769 18
|
||||
```
|
||||
|
||||
|
||||
## Avoid These
|
||||
|
||||
The starting words with the worst accuracy:
|
||||
|
||||
```
|
||||
sort -k2nr results.avg | sed 18q | pr -t -3
|
||||
|
||||
jumpy 3.997408 21 juicy 3.954212 39 squib 3.927862 28
|
||||
jumbo 3.996976 25 quake 3.952052 38 quark 3.926566 30
|
||||
buxom 3.995248 23 jerky 3.950756 31 quoth 3.920950 33
|
||||
quick 3.987041 36 equip 3.939957 22 gawky 3.918790 22
|
||||
quack 3.974514 23 quasi 3.938661 32 unzip 3.915335 24
|
||||
quirk 3.964147 40 epoxy 3.934773 27 judge 3.914903 33
|
||||
```
|
||||
|
||||
The starting words with the most failures (missed words):
|
||||
|
||||
```
|
||||
sort -k3nr results.avg | sed 18q | pr -t -3
|
||||
|
||||
query 3.893305 43 juicy 3.954212 39 enjoy 3.890713 37
|
||||
quite 3.835421 42 quota 3.881641 39 gauze 3.878186 37
|
||||
yield 3.740821 41 quake 3.952052 38 oxide 3.888121 37
|
||||
juice 3.847084 40 quiet 3.857451 38 fiery 3.772786 36
|
||||
quirk 3.964147 40 quote 3.829374 38 quail 3.893737 36
|
||||
axion 3.796544 39 unify 3.862203 38 quick 3.987041 36
|
||||
```
|
||||
|
||||
The worst target words, for any starting word (N out of 1566):
|
||||
|
||||
```
|
||||
./worst
|
||||
|
||||
wound 1340 jaunt 1254 hatch 1157 foyer 1109 waste 1057
|
||||
found 997 shave 945 wight 943 willy 790 catch 779
|
||||
boxer 762 jolly 751 graze 626 rower 611 fatty 598
|
||||
roger 568 taunt 520 watch 497 witty 483 wooer 451
|
||||
tight 449 bound 442 swore 415 taste 405 mower 378
|
||||
hover 374 bunch 371 shake 358 racer 348 rarer 294
|
||||
paper 289 water 285 stave 271 ferry 250 fever 242
|
||||
fully 241 paddy 239 fight 225 parer 219 taffy 207
|
||||
frown 196 joker 195 filly 188 batty 179 lowly 179
|
||||
staff 176 jazzy 174 piper 152 vying 152 swear 151
|
||||
```
|
||||
|
||||
|
||||
## SPOILER Deep Dive on Near Misses SPOILER
|
||||
|
||||
Dissecting the failed targets when starting with `blast`. Recall `blast`
|
||||
only misses 4 words out of all 2315:
|
||||
|
||||
```
|
||||
foyer jaunt shave wound
|
||||
```
|
||||
|
||||
These four words have common sub-patterns, which in hard-mode is difficult
|
||||
to disambiguate. Using `run dict blast $word`, here are the grep sub-patterns
|
||||
and counts for these four words as revealed in the output:
|
||||
|
||||
```
|
||||
foyer 25 grep '^.o.er' dict | wc -l
|
||||
jaunt 6 grep '^.aunt' dict | wc -l
|
||||
shave 7 grep '^sha.e' dict | wc -l
|
||||
wound 8 grep '^.ound' dict | wc -l
|
||||
```
|
||||
|
||||
Looking at the patterns, the program is making guesses that just happen to
|
||||
select the correct word last in its choices. In all cases, on the seventh
|
||||
guess, the program has the correct answer using `blast` as the starting guess.
|
||||
It is easy to do an exhaustive look for only four words, but as the count
|
||||
goes up, so does the work.
|
||||
|
||||
Several variations were attempted, including randomization of the few results
|
||||
remaining. Besides being non-deterministic (this time it wins, next time it
|
||||
loses), better results were obtained with other changes to the selection
|
||||
algorithm. Some small insight into the algorithm used may be seen by the
|
||||
`grep` command lines, although there are additional insights used within
|
||||
the program that improve significantly upon these results.
|
||||
|
||||
```
|
||||
./run dict blast foyer | grep ^gen
|
||||
gen: target: foyer 2315
|
||||
gen: blast bbbbb 429 grep -v '[blast]' dict | wc -l
|
||||
gen: drone byyby 27 grep r dict | grep o | grep e | grep -v '[blastdn]' | wc -l
|
||||
gen: cower bgbgg 8 grep '^.o.er' dict | grep -v '[blastdncw]'
|
||||
foyer homer hover joker
|
||||
mover poker roger rover
|
||||
gen: mover bgbgg 4 grep '.o.er' dict | grep -v '[blastdncwmv]'
|
||||
foyer joker poker roger
|
||||
gen: poker bgbgg rm poker joker (foyer roger)
|
||||
gen: roger ygbgg rm roger (foyer)
|
||||
gen result end=0: n 6 lose: foyer
|
||||
|
||||
---------------
|
||||
|
||||
./run dict blast jaunt | grep ^gen
|
||||
gen: target: jaunt 2315
|
||||
gen: blast bbybg 46 grep 't$' dict | grep a | grep -v '[bls]' | wc -l
|
||||
gen: daunt bgggg 5 grep '^.aunt$' dict | grep -v '[blsd]'
|
||||
gaunt haunt jaunt taunt
|
||||
vaunt
|
||||
gen: haunt bgggg rm haunt (gaunt, jaunt, taunt, vaunt)
|
||||
gen: gaunt bgggg rm guant (jaunt, taunt, vaunt)
|
||||
gen: vaunt bgggg rm vaunt (jaunt, taunt)
|
||||
gen: taunt ygggg rm taunt (jaunt)
|
||||
gen result end=0: n 6 lose: jaunt
|
||||
|
||||
---------------
|
||||
|
||||
./run dict blast shave | grep ^gen
|
||||
gen: target: shake 2315
|
||||
gen: blast bbgyb 52 grep '^..a' dict | grep s | grep -v '[blt]' | wc -l
|
||||
gen: share gggbg 5 grep '^sha.e' dict | grep -v '[bltr]'
|
||||
shade shake shame shape
|
||||
shave
|
||||
gen: shade gggbg rm shade (shake shame shape shave)
|
||||
gen: shape gggbg rm shape (shake shame shave)
|
||||
gen: shame gggbg rm shame (shake shave)
|
||||
gen: shake gggbg rm shake (shave)
|
||||
gen result end=0: n 6 lose: shave
|
||||
|
||||
---------------
|
||||
|
||||
./run dict blast wound | grep ^gen
|
||||
gen: target: wound 2315
|
||||
gen: blast bbbbb 429 grep -v '[blast]' dict | wc -l
|
||||
gen: drone ybygb 7 grep 'n.$' dict | grep d | grep o | grep -v '[blastre]' | wc -l
|
||||
gen: pound bgggg 4 grep '^.ound' dict | grep -v '[blastreh]'
|
||||
found hound mound wound
|
||||
gen: mound bgggg rm mound (found, hound, wound)
|
||||
gen: hound bgggg rm hound (found, wound)
|
||||
gen: found bgggg rm found (wound)
|
||||
gen result end=0: n 6 lose: wound
|
||||
```
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
w=$1; : ${w:?echo "usage: $0 target_word" >&2; exit 1}
|
||||
|
||||
rank results/$w |
|
||||
sed -n 7,\$p |
|
||||
tr '\t' '\n' |
|
||||
awk '$1 != "" {print $1}' |
|
||||
sort -u |
|
||||
while read a; do
|
||||
GUESSES=9 run dict $w $a
|
||||
done |
|
||||
grep result
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
dict=$1
|
||||
: ${dict:=dict}
|
||||
|
||||
echo first
|
||||
seq a z | while read a; do /bin/echo -n "$a: "; grep ^$a $dict | wc -l; done | sort -k2nr
|
||||
echo second
|
||||
seq a z | while read a; do /bin/echo -n "$a: "; grep ^.$a $dict | wc -l; done | sort -k2nr
|
||||
echo third
|
||||
seq a z | while read a; do /bin/echo -n "$a: "; grep ^..$a $dict | wc -l; done | sort -k2nr
|
||||
echo fourth
|
||||
seq a z | while read a; do /bin/echo -n "$a: "; grep ^...$a $dict | wc -l; done | sort -k2nr
|
||||
echo last
|
||||
seq a z | while read a; do /bin/echo -n "$a: "; grep ^....$a $dict | wc -l; done | sort -k2nr
|
||||
@@ -0,0 +1,86 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
/*
|
||||
* Wordle generator - text mode
|
||||
* This program works in coordination with the obfuscated code
|
||||
* to allow one to play more rapidly (e.g. test the algorithm)
|
||||
* or just to play along in text mode.
|
||||
*
|
||||
* This version is a pale imitation of the Real Wordle(tm).
|
||||
* If you want to get the real experience, please visit:
|
||||
*
|
||||
* https://www.nytimes.com/games/wordle/index.html
|
||||
*/
|
||||
|
||||
static int
|
||||
check(char *w, char *target)
|
||||
{
|
||||
printf("%.5s ", w);
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
if (w[i] == target[i])
|
||||
putchar('g');
|
||||
else if (memchr(target, w[i], 5))
|
||||
putchar('y');
|
||||
else
|
||||
putchar('b');
|
||||
}
|
||||
putchar('\n');
|
||||
fflush(stdout);
|
||||
return memcmp(w, target, 5) == 0;
|
||||
}
|
||||
|
||||
int
|
||||
main(int ac, char **av)
|
||||
{
|
||||
char words[78557][5];
|
||||
char buf[100];
|
||||
int cnt = 0, win = 0;
|
||||
int nguesses = 6;
|
||||
|
||||
if (ac < 2) {
|
||||
fprintf(stderr, "usage: %s dict [target]\n", av[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (getenv("GUESSES")) {
|
||||
nguesses = atoi(getenv("GUESSES"));
|
||||
// fprintf(stderr, "using %d guesses\n", nguesses);
|
||||
}
|
||||
|
||||
FILE *fp = fopen(av[1], "r");
|
||||
if (!fp) {
|
||||
perror(av[1]);
|
||||
exit(1);
|
||||
}
|
||||
while (fgets(buf, sizeof buf, fp)) {
|
||||
if (buf[5] != '\n')
|
||||
continue;
|
||||
memcpy(words[cnt++], buf, 5);
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
srandom(time(0) ^ getpid());
|
||||
|
||||
char *target = ac == 3 ? av[2] : words[random() % cnt];
|
||||
getenv("CHEAT") && printf("target: %.5s\n", target);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < nguesses; ) {
|
||||
printf("? "); fflush(stdout);
|
||||
if (!fgets(buf, sizeof buf, stdin))
|
||||
break;
|
||||
if (buf[5] != '\n') {
|
||||
printf("you must enter 5 letters\n");
|
||||
continue;
|
||||
}
|
||||
++i;
|
||||
if ((win = check(buf, target)))
|
||||
break;
|
||||
}
|
||||
printf("%c %d %s: %.5s\n", win ? 'y' : 'n', i, win ? "good" : "lose", target);
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
dir=$1
|
||||
: ${dir:=results}
|
||||
|
||||
for name in $dir/*; do
|
||||
./avg $name
|
||||
done | sed "s#$dir/##" | tr : ' '
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
#define J(J) for (\
|
||||
_ j=0; j<5; ++j) J;
|
||||
#define/*IOCCC*/I \
|
||||
\
|
||||
\
|
||||
\
|
||||
_ W,_ O,_ R,_ D,_*L,_*E
|
||||
|
||||
|
||||
#define A(A )for(_ j=0; !o&&j<5&&(k = t[l][j]); ++j)A&&++o;
|
||||
typedef/* ; ; */void q; typedef int _ ; typedef char/* */p;
|
||||
struct{ p a [257],b[9][ 5],c[5],d[5 ]; _ e,f; } i;p t[78557
|
||||
][5]; _ s,a []={ 9,9,9, 10,13,18,27 ,39,55,1,18 ,2,1,1,35,2
|
||||
,19,18,1,52 ,36,35,20,3 ,2,19,18,18 ,69,2,53,1, 52,37,3,20,
|
||||
36,19,35,18 ,52,86,2,53 ,70,1,69,38 ,4,21,3,37, 19,36,35,25
|
||||
,10,+17,15, 26,9,11,12, 23,2,06,18, 13,20,22,14 ,1,24,19,21
|
||||
|
||||
,16,5,7,4,8 ,3},u=' ';_ W(p*a,p*b){ for(p*c=a+5 ;a<c;)*a++=
|
||||
*b++;return 0; } _ O(p* a,p b){ p*c =a+5; for(; a<c&&*a-b;)
|
||||
++a; return a<c?5-(a-c) :0; } _ R(p *a, ... ) { va_list b ;
|
||||
va_start(b, a); vprintf (a,b); exit (1); } q D( p*a){ if (s
|
||||
==sizeof t/ 5)R("limit" " %d\n",s); p*b=s[t],i, j; for(i=j=
|
||||
0; i<7&&!j; ++i)if(!(j= *a==10?i:0) )*b++=u|* a ++; j-5||++
|
||||
s; } q L(p* a,_ b){ for (_ l=0,o=0, k; l<s; o=0 ){ A(i.c[j]
|
||||
|
||||
&&k-i.c[j]) A(i.a[k])A( i.d[j]&&!O( t[l],i.d[j] ))for(_ f=i
|
||||
.e; f--&&!o ; )A(i.b[f] [j]==k)if(! o){ J(o+=t[ l][j]==a[j]
|
||||
)o=o==5?b!= 5:0; } o?W( t[l],t[--s] ) :++l; } } _ e(I){ for
|
||||
(; O<D; )L[ R++]=E[O+++ D*W];return R; } q S( _ O,_*l){ for
|
||||
(_*s=&a[a[O ]],*e=a[-~O ]+s-a[O]; s <e; ){ _ i= *s++,j=i&15
|
||||
,k=l[i>>=4] <l[+j]?k=l[ i],l[i]=l[j ],l[j]=k:i; } } _ o(I){
|
||||
_ o=0, w=0; for(; o<D&w <D; )L[R++] =E[o+D*W]>= E[w+D*O]?E[
|
||||
o+++D*W]:E[ w +++ D*O]; return e(O, w,e(W,o,R,D ,L,E),D,L,E
|
||||
|
||||
); } q l( _ n,_*f){ for (_* e=f+26, i,j; f<e&&* f>u; f+= i)
|
||||
{ for(i=1,j =*f/u; i <n &&f[i]>>5== j; )++i;for (j=0; j <i;
|
||||
++j)f[j] &= 31,f[j]|=a[ f[j]+a[~-9] ]<<5; S(i,f ); } } q v(
|
||||
_ a,_*w,_*k ){ o(2,3,o( 0,1,0,a,w,k ),a,w,k); o (0,1,0,a+a,
|
||||
k,w); l(a,k ); } p*E(p* d){ _ l,j,k =u,b[u] ,c[ k]; p*e[97]
|
||||
[5 ]={ 0} ; for(l=0; l< k; ++l)c[l] =l; for(l=0 ; l<s; ++l)
|
||||
J(c[t[l][j] -97]+=k)for (l= j=7; j< 22; j+=l)S( l,c+j-l); v
|
||||
|
||||
(l,b,c);for (l= 0; l<k; ++l)b[c[l]& ~-k]=l; for (k*=3,l= 0;
|
||||
l<s; ++l) { _ i=0; J( i +=b[t[l][j] -97])if(i<k )J(e[i][ j]
|
||||
||(e[i][j]= t[l],j=4))} for(l=0; l< k; ++l)for( p*b=0,k=j=0
|
||||
; j<5&&(b=e [l][j]); k= !++j){ p c[ 32]={0} ; d =*d-120?d:b
|
||||
; if(s>2)J( k+=++c[b[j] -97]>1); if (!k) return b; } return
|
||||
d; } p*r(p* b){ _ k, l; for(_ j=k=l =0; j<5; ++ j) { signed
|
||||
char n=b[j] ,o=b[j-~5]+ ~0x66; (o?i .b[i.e]:i.c )[j]=n; !o?
|
||||
|
||||
i.a[n]=!++k :O(i.d,n)|| (*(o<0?&i.a [n]:&i.d[i. f++])=l=n);
|
||||
} i.e += !! l; L(b, k); return E("" "xyzzy"); } _ main(_ n,
|
||||
char**v){ p *j=i .c-97, *l=j-11; n- 2?R("usage" ": %s dict"
|
||||
"\n",* v):5 ; ; FILE*k= fopen(*++v, "r"); if(!k ) return //
|
||||
perror(*v), 1; ; while( fgets(j, u^ n,k)) D(j); fclose (k);
|
||||
; ; setbuf( stdout, 0); while(~-s){ printf("? " ); while(~(
|
||||
n=getchar() )&&n-10&&l< j)*l++=n; l <j&&R("inp" "ut: guess"
|
||||
" color\n") ;printf("%" ".5s\n",r(l =j+~10)); } return 0; }
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
#define J(J) for (\
|
||||
_ j=0; j<5; ++j) J;
|
||||
#define/*IOCCC*/I \
|
||||
\
|
||||
\
|
||||
\
|
||||
_ W,_ O,_ R,_ D,_*L,_*E
|
||||
|
||||
|
||||
#define A(A )for(_ j=0; !o&&j<5&&(k = t[l][j]); ++j)A&&++o;
|
||||
typedef/* ; ; */void q; typedef int _ ; typedef char/* */p;
|
||||
struct{ p a [257],b[9][ 5],c[5],d[5 ]; _ e,f; } i;p t[78557
|
||||
][5]; _ s,a []={ 9,9,9, 10,13,18,27 ,39,55,1,18 ,2,1,1,35,2
|
||||
,19,18,1,52 ,36,35,20,3 ,2,19,18,18 ,69,2,53,1, 52,37,3,20,
|
||||
36,19,35,18 ,52,86,2,53 ,70,1,69,38 ,4,21,3,37, 19,36,35,25
|
||||
,10,+17,15, 26,9,11,12, 23,2,06,18, 13,20,22,14 ,1,24,19,21
|
||||
|
||||
,16,5,7,4,8 ,3},u=' ';_ W(p*a,p*b){ for(p*c=a+5 ;a<c;)*a++=
|
||||
*b++;return 0; } _ O(p* a,p b){ p*c =a+5; for(; a<c&&*a-b;)
|
||||
++a; return a<c?5-(a-c) :0; } _ R(p *a, ... ) { va_list b ;
|
||||
va_start(b, a); vprintf (a,b); exit (1); } q D( p*a){ if (s
|
||||
==sizeof t/ 5)R("limit" " %d\n",s); p*b=s[t],i, j; for(i=j=
|
||||
0; i<7&&!j; ++i)if(!(j= *a==10?i:0) )*b++=u|* a ++; j-5||++
|
||||
s; } q L(p* a,_ b){ for (_ l=0,o=0, k; l<s; o=0 ){ A(i.c[j]
|
||||
|
||||
&&k-i.c[j]) A(i.a[k])A( i.d[j]&&!O( t[l],i.d[j] ))for(_ f=i
|
||||
.e; f--&&!o ; )A(i.b[f] [j]==k)if(! o){ J(o+=t[ l][j]==a[j]
|
||||
)o=o==5?b!= 5:0; } o?W( t[l],t[--s] ) :++l; } } _ e(I){ for
|
||||
(; O<D; )L[ R++]=E[O+++ D*W];return R; } q S( _ O,_*l){ for
|
||||
(_*s=&a[a[O ]],*e=a[-~O ]+s-a[O]; s <e; ){ _ i= *s++,j=i&15
|
||||
,k=l[i>>=4] <l[+j]?k=l[ i],l[i]=l[j ],l[j]=k:i; } } _ o(I){
|
||||
_ o=0, w=0; for(; o<D&w <D; )L[R++] =E[o+D*W]>= E[w+D*O]?E[
|
||||
o+++D*W]:E[ w +++ D*O]; return e(O, w,e(W,o,R,D ,L,E),D,L,E
|
||||
|
||||
); } q l( _ n,_*f){ for (_* e=f+26, i,j; f<e&&* f>u; f+= i)
|
||||
{ for(i=1,j =*f/u; i <n &&f[i]>>5== j; )++i;for (j=0; j <i;
|
||||
++j)f[j] &= 31,f[j]|=a[ f[j]+a[~-9] ]<<5; S(i,f ); } } q v(
|
||||
_ a,_*w,_*k ){ o(2,3,o( 0,1,0,a,w,k ),a,w,k); o (0,1,0,a+a,
|
||||
k,w); l(a,k ); } p*E(p* d){ _ l,j,k =u,b[u] ,c[ k]; p*e[97]
|
||||
[5 ]={ 0} ; for(l=0; l< k; ++l)c[l] =l; for(l=0 ; l<s; ++l)
|
||||
J(c[t[l][j] -97]+=k)for (l= j=7; j< 22; j+=l)S( l,c+j-l); v
|
||||
|
||||
(l,b,c);for (l= 0; l<k; ++l)b[c[l]& ~-k]=l; for (k*=3,l= 0;
|
||||
l<s; ++l) { _ i=0; J( i +=b[t[l][j] -97])if(i<k )J(e[i][ j]
|
||||
||(e[i][j]= t[l],j=4))} for(l=0; l< k; ++l)for( p*b=0,k=j=0
|
||||
; j<5&&(b=e [l][j]); k= !++j){ p c[ 32]={0} ; d =*d-120?d:b
|
||||
; if(s>2)J( k+=++c[b[j] -97]>1); if (!k) return b; } return
|
||||
d; } p*r(p* b){ _ k, l; for(_ j=k=l =0; j<5; ++ j) { signed
|
||||
char n=b[j] ,o=b[j-~5]+ ~0x66; (o?i .b[i.e]:i.c )[j]=n; !o?
|
||||
|
||||
i.a[n]=!++k :O(i.d,n)|| (*(o<0?&i.a [n]:&i.d[i. f++])=l=n);
|
||||
} i.e += !! l; L(b, k); return E("" "xyzzy"); } _ main(_ n,
|
||||
char**v){ p *j=i .c-97, *l=j-11; n- 2?R("usage" ": %s dict"
|
||||
"\n",* v):5 ; ; FILE*k= fopen(*++v, "r"); if(!k ) return //
|
||||
perror(*v), 1; ; while( fgets(j, u^ n,k)) D(j); fclose (k);
|
||||
; ; setbuf( stdout, 0); while(~-s){ printf("? " ); while(~(
|
||||
n=getchar() )&&n-10&&l< j)*l++=n; l <j&&R("inp" "ut: guess"
|
||||
" color\n") ;printf("%" ".5s\n",r(l =j+~10)); } return 0; }
|
||||
|
||||
|
||||
|
||||
+23999
File diff suppressed because it is too large.
Load diff
+23783
File diff suppressed because it is too large.
Load diff
+25469
File diff suppressed because it is too large.
Load diff
+24014
File diff suppressed because it is too large.
Load diff
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
: ${dir:=results}
|
||||
word=$1
|
||||
echo $word | grep -q /
|
||||
if test $? -eq 1; then word=$dir/$word; fi
|
||||
|
||||
grep good: $word | awk '{n[$5]++}END{for(i=1; i<7; ++i)print i,n[i]}' | sort -k1n
|
||||
grep lose: $word | awk '{print $NF}' | pr -t -a -5
|
||||
@@ -0,0 +1,26 @@
|
||||
/* clang-format --style=LLVM < prog.c | reveal */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int start = 0, len;
|
||||
char buf[128];
|
||||
|
||||
while (fgets(buf, sizeof buf, stdin)) {
|
||||
len = strlen(buf);
|
||||
if (len > 3 && !isspace(buf[0])) {
|
||||
char c = buf[2];
|
||||
if (c == 'i') start = 1;
|
||||
if (c == 'm') start = 0;
|
||||
if (!start) continue;
|
||||
if (buf[2] == '*') c = buf[3];
|
||||
if (isalpha(c)) putchar(c);
|
||||
} else if (start && len > 6 && buf[6] == ']')
|
||||
putchar(buf[4]);
|
||||
}
|
||||
putchar('\n');
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* run - connect gen and prog via pipes
|
||||
*
|
||||
* one-shot: run dict
|
||||
* specific: run dict $start $target
|
||||
* automate: cat dict | while read a; do run dict $start $a; done
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
static int DB;
|
||||
|
||||
static int
|
||||
error(char *who)
|
||||
{
|
||||
perror(who);
|
||||
kill(0, SIGKILL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
xread(int fd, char *buf, int len)
|
||||
{
|
||||
int remain = len;
|
||||
int t = 0;
|
||||
|
||||
if (DB) { printf("xread %d:", len); fflush(stdout); }
|
||||
|
||||
do {
|
||||
int n = read(fd, buf + t, remain);
|
||||
if (n < 0) error("read");
|
||||
if (n == 0) return t;
|
||||
if (n <= remain) {
|
||||
remain -= n;
|
||||
t += n;
|
||||
}
|
||||
} while (t != len);
|
||||
buf[t] = 0;
|
||||
|
||||
if (DB) {
|
||||
printf(" %s", buf);
|
||||
if (buf[t-1] != '\n') printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static void
|
||||
spawn(int r[2], int w[2], char **ev, char *path, char *name, char *dict, char *opt)
|
||||
{
|
||||
pipe(r) && error("pipe r");
|
||||
pipe(w) && error("pipe w");
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == -1)
|
||||
error("fork");
|
||||
|
||||
if (pid == 0) {
|
||||
char *v[4] = { name, dict, opt, 0 };
|
||||
|
||||
dup2(r[0], 0) < 0 && error("dup2 r[0]");
|
||||
dup2(w[1], 1) < 0 && error("dup2 w[1]");
|
||||
|
||||
close(r[1]);
|
||||
close(w[0]);
|
||||
|
||||
execve(path, v, ev);
|
||||
error(path);
|
||||
}
|
||||
|
||||
close(r[0]);
|
||||
close(w[1]);
|
||||
}
|
||||
|
||||
int
|
||||
main(int ac, char **av, char **ev)
|
||||
{
|
||||
int pgr[2], pgw[2]; // gen r/w
|
||||
int ppr[2], ppw[2]; // prog r/w
|
||||
|
||||
static char guess[20], report[20];
|
||||
static char xyzzy[] = "xyzzy";
|
||||
char *cp, *prog = "./prog";
|
||||
int n, end = 0;
|
||||
int nguesses = 6;
|
||||
|
||||
if (ac < 2) {
|
||||
fprintf(stderr, "usage: %s dict [start [target]]\n", av[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
DB = !!getenv("DEBUG");
|
||||
|
||||
if ((cp = getenv("GUESSES")))
|
||||
nguesses = atoi(cp);
|
||||
if ((cp = getenv("PROG")))
|
||||
prog = cp;
|
||||
|
||||
spawn(pgr, pgw, ev, "./gen", "gen", av[1], ac==4 ? av[3] : 0);
|
||||
spawn(ppr, ppw, ev, prog, "prog", av[1], 0);
|
||||
|
||||
// wait for gen to be ready; read the prompt
|
||||
char buf[20];
|
||||
xread(pgw[0], buf, 2);
|
||||
if (buf[0] != '?') {
|
||||
xread(pgw[0], buf+2, 12); // target: guess
|
||||
printf("gen: %s", buf);
|
||||
xread(pgw[0], buf, 2);
|
||||
}
|
||||
|
||||
// wait for prog prompt
|
||||
xread(ppw[0], buf, 2);
|
||||
|
||||
memcpy(guess, ac>2 ? av[2] : "blast", 5);
|
||||
guess[5] = '\n'; // mimic reading from stdin
|
||||
|
||||
for (int i = 0; i < nguesses && end != 1; ++i) {
|
||||
printf("guess%d: %s", i+1, guess);
|
||||
|
||||
n = write(pgr[1], guess, 6);
|
||||
if (n < 0) error("write pgw[1]");
|
||||
n = xread(pgw[0], report, 12);
|
||||
if (n != 12) {
|
||||
if (n < 0) error("read pgr[0]");
|
||||
printf("bad read from pgr[0]: %d\n", n);
|
||||
return 2;
|
||||
}
|
||||
|
||||
printf("gen: %s", report);
|
||||
|
||||
xread(pgw[0], guess, 2); // read the prompt
|
||||
if (guess[0] != '?') {
|
||||
xread(pgw[0], guess+2, 14);
|
||||
printf("gen result end=%d: %s", end, guess);
|
||||
if (end == 2) {
|
||||
close(pgr[1]);
|
||||
close(ppr[1]);
|
||||
return 0;
|
||||
}
|
||||
close(pgw[0]);
|
||||
close(pgr[1]);
|
||||
end = 1;
|
||||
}
|
||||
|
||||
if (end == 2) {
|
||||
// cannot write to prog, it exited on winner, but gen disagrees
|
||||
printf("ERROR: prog reported win, gen does not\n");
|
||||
close(pgr[1]);
|
||||
close(ppr[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
n = write(ppr[1], report, n);
|
||||
if (n < 0) error("ppw[1]");
|
||||
n = xread(ppw[0], guess, 6);
|
||||
if (n != 6) {
|
||||
if (n < 0) error("read ppr");
|
||||
printf("bad read from pipe_prog: %d {%.*s}\n", n, n, guess);
|
||||
return 3;
|
||||
}
|
||||
if (strncmp(guess, xyzzy, sizeof(xyzzy)-1) == 0) {
|
||||
printf("ERROR: desired word not in this dictionary\n");
|
||||
close(pgr[1]);
|
||||
close(ppr[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// might not prompt, just exit
|
||||
if (xread(ppw[0], report, 2) == 0) { // read the prompt
|
||||
printf("prog: EOF\n");
|
||||
if (end == 1) {
|
||||
close(pgr[1]);
|
||||
close(ppr[1]);
|
||||
return 0;
|
||||
}
|
||||
end = 2;
|
||||
close(ppr[1]);
|
||||
close(ppw[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
blast ybybb
|
||||
amber gbyyb
|
||||
adobe gygyg
|
||||
abode ggggg
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
blast bbybg
|
||||
daunt bgggg
|
||||
haunt bgggg
|
||||
gaunt bgggg
|
||||
vaunt bgggg
|
||||
taunt ygggg
|
||||
@@ -0,0 +1,3 @@
|
||||
terns ybbbb
|
||||
loath gbbyy
|
||||
light ggggg
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# try.sh - demonstrate 2024/burton
|
||||
|
||||
# make sure CC is set so that when we do make CC="$CC" it isn't empty. Doing it
|
||||
# this way allows us to have the user specify a different compiler in an easy way.
|
||||
#
|
||||
[[ -z "$CC" ]] && CC="cc"
|
||||
|
||||
# make sure the program has been built
|
||||
#
|
||||
make CC="$CC" all >/dev/null || exit 1
|
||||
|
||||
# clear the screen
|
||||
#
|
||||
clear
|
||||
|
||||
# try the program
|
||||
#
|
||||
read -r -n 1 -p "Press any key to run: ./prog: "
|
||||
echo 1>&2
|
||||
echo 1>&2
|
||||
cat test.light 1>&2
|
||||
echo 1>&2
|
||||
echo '=-=-=' 1>&2
|
||||
echo 1>&2
|
||||
./prog dict < test.light
|
||||
echo 1>&2
|
||||
@@ -0,0 +1,165 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef void q;
|
||||
typedef int _;
|
||||
typedef char p;
|
||||
|
||||
struct {
|
||||
p a[256], b[9][5], c[5], d[5];
|
||||
_ e, f;
|
||||
} i;
|
||||
p t[78557][5];
|
||||
_ s, a[] = {
|
||||
9, 9, 9, 10, 13, 18, 27, 39, 55, 1, 18, 2, 1, 1,
|
||||
35, 2, 19, 18, 1, 52, 36, 35, 20, 3, 2, 19, 18, 18,
|
||||
69, 2, 53, 1, 52, 37, 3, 20, 36, 19, 35, 18, 52, 86,
|
||||
2, 53, 70, 1, 69, 38, /* 36 */ 4, 21, 3, 37, 19,
|
||||
36, 35, 25, 10, 17, 15, 26, 9, 11, 12, 23, 2, 6, 18,
|
||||
13, 20, 22, 14, 1, 24, 19, 21, 16, 5, 7, 4, 8, 3
|
||||
} , u = ' ';
|
||||
|
||||
_ W(p *a, p *b) {
|
||||
for (p *c = a + 5; a < c; )
|
||||
*a++ = *b++;
|
||||
return 0;
|
||||
}
|
||||
_ O(p *a, p b) {
|
||||
p *c = a + 5;
|
||||
for (; a < c && *a - b; )
|
||||
++a;
|
||||
return a < c ? 5 - (a - c) : 0;
|
||||
}
|
||||
_ R(p *a, ...) {
|
||||
va_list b;
|
||||
va_start(b, a);
|
||||
vprintf(a, b);
|
||||
exit(1);
|
||||
}
|
||||
q D(p *a) {
|
||||
if (s == sizeof t / 5)
|
||||
R("limit %d\n", s);
|
||||
p *b = s[t], i, j;
|
||||
for (i = j = 0; i < 7 && !j; ++i)
|
||||
if (!(j = *a == 10 ? i : 0))
|
||||
*b++ = u | *a++;
|
||||
j - 5 || ++s;
|
||||
}
|
||||
q L(p *a, _ b) {
|
||||
for (_ l = 0, o = 0, k; l < s; o = 0) {
|
||||
for (_ j = 0; !o && j < 5 && (k = t[l][j]); ++j)
|
||||
i.c[j] && k - i.c[j] && ++o;
|
||||
for (_ j = 0; !o && j < 5 && (k = t[l][j]); ++j)
|
||||
i.a[k] && ++o;
|
||||
for (_ j = 0; !o && j < 5 && (k = t[l][j]); ++j)
|
||||
i.d[j] && !O(t[l], i.d[j]) && ++o;
|
||||
for (_ f = i.e; f-- && !o; )
|
||||
for (_ j = 0; !o && j < 5 && (k = t[l][j]); ++j)
|
||||
i.b[f][j] == k && ++o;
|
||||
if (!o) {
|
||||
for (_ j = 0; j < 5; ++j)
|
||||
o += t[l][j] == a[j];
|
||||
o = o == 5 ? b != 5 : 0;
|
||||
}
|
||||
o ? W(t[l], t[--s]) : ++l;
|
||||
}
|
||||
}
|
||||
_ e(_ W, _ O, _ R, _ D, _ *L, _ *E) {
|
||||
for (; O < D; )
|
||||
L[R++] = E[O++ + D * W];
|
||||
return R;
|
||||
}
|
||||
q S(_ O, _ *l) {
|
||||
for (_ *s = &a[a[O]], *e = a[-~O] + s - a[O]; s < e; ) {
|
||||
_ i = *s++,
|
||||
j = i & 15,
|
||||
k = l[i >>= 4] < l[j] ? k = l[i], l[i] = l[j], l[j] = k : i;
|
||||
}
|
||||
}
|
||||
_ o(_ W, _ O, _ R, _ D, _ *L, _ *E) {
|
||||
_ o = 0, w = 0;
|
||||
for (; o < D & w < D; )
|
||||
L[R++] = E[o + D * W] >= E[w + D * O]
|
||||
? E[o++ + D * W]
|
||||
: E[w++ + D * O];
|
||||
return e(O, w, e(W, o, R, D, L, E), D, L, E);
|
||||
}
|
||||
q l(_ n, _ *f) {
|
||||
for (_ *e = f + 26, i, j; f < e && *f > u; f += i) {
|
||||
for (i = 1, j = *f / u; i < n && f[i] >> 5 == j; )
|
||||
++i;
|
||||
for (j = 0; j < i; ++j)
|
||||
f[j] &= 31,
|
||||
f[j] |= a[f[j] + a[~-9]] << 5;
|
||||
S(i, f);
|
||||
}
|
||||
}
|
||||
q v(_ a, _ *w, _ *k) {
|
||||
o(2, 3, o(0, 1, 0, a, w, k), a, w, k);
|
||||
o(0, 1, 0, a + a, k, w);
|
||||
l(a, k);
|
||||
}
|
||||
p *E(p *d) {
|
||||
_ l, j, k = u, b[u], c[k];
|
||||
p *e[97][5] = { 0 } ;
|
||||
for (l = 0; l < k; ++l)
|
||||
c[l] = l;
|
||||
for (l = 0; l < s; ++l)
|
||||
for (_ j = 0; j < 5; ++j)
|
||||
c[t[l][j] - 97] += k;
|
||||
for (l = j = 7; j < 22; j += l)
|
||||
S(l, c + j - l);
|
||||
v(l, b, c);
|
||||
for (l = 0; l < k; ++l)
|
||||
b[c[l] & ~-k] = l;
|
||||
for (k *= 3, l = 0; l < s; ++l) {
|
||||
_ i = 0;
|
||||
for (_ j = 0; j < 5; ++j)
|
||||
i += b[t[l][j] - 97];
|
||||
if (i < k)
|
||||
for (_ j = 0; j < 5; ++j)
|
||||
e[i][j] || (e[i][j] = t[l], j = 4);
|
||||
}
|
||||
for (l = 0; l < k; ++l)
|
||||
for (p *b = 0, k = j = 0; j < 5 && (b = e[l][j]); k = !++j) {
|
||||
p c[32] = { 0 } ;
|
||||
d = *d - 120 ? d : b;
|
||||
if (s > 2)
|
||||
for (_ j = 0; j < 5; ++j)
|
||||
k += ++c[b[j] - 97] > 1;
|
||||
if (!k)
|
||||
return b;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
p *r(p *b) {
|
||||
_ k, l;
|
||||
for (_ j = k = l = 0; j < 5; ++j) {
|
||||
signed char n = b[j], o = b[j - ~5] + ~0x66;
|
||||
(o ? i.b[i.e] : i.c)[j] = n;
|
||||
!o ? i.a[n] = !++k : O(i.d, n) || (*(o < 0 ? &i.a[n] : &i.d[i.f++]) = l = n);
|
||||
}
|
||||
i.e += !!l;
|
||||
L(b, k);
|
||||
return E("xyzzy");
|
||||
}
|
||||
_ main(_ n, char **v) {
|
||||
p *j = i.c - 97, *l = j - 11;
|
||||
n - 2 ? R("usage: %s dict\n", *v) : 5;
|
||||
FILE *k = fopen(*++v, "r");
|
||||
if (!k)
|
||||
return perror(*v), 1;
|
||||
while (fgets(j, u ^ n, k))
|
||||
D(j);
|
||||
fclose(k);
|
||||
setbuf(stdout, 0);
|
||||
while (~-s) {
|
||||
printf("? ");
|
||||
while (~(n = getchar()) && n - 10 && l < j)
|
||||
*l++ = n;
|
||||
l < j && R("input: guess color\n");
|
||||
printf("%.5s\n", r(l = j + ~10));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
test $# -eq 6 || { echo must have all six scores; exit 1; }
|
||||
echo "($1*1 + $2*2 + $3*3 + $4*4 + $5*5 + $6*6) / ($1+$2+$3+$4+$5+$6)" | bc -l | awk '{printf "%.04f\n", $1 }'
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
# usage: echo terns | word.result
|
||||
# usage: cat dict | word.result
|
||||
|
||||
dir=$1
|
||||
: ${dir:=results}
|
||||
|
||||
d=$2
|
||||
: ${d:=dict}
|
||||
|
||||
# for each word as a starting guess
|
||||
# run the sim for each target word
|
||||
|
||||
while read w; do
|
||||
echo $w;
|
||||
cat dict | while read t; do
|
||||
./run $d $w $t
|
||||
done > $dir/$w
|
||||
done
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
dir=$1
|
||||
: ${dir:=results}
|
||||
lines=$2
|
||||
: ${lines:=10}
|
||||
|
||||
for name in $dir/*; do
|
||||
grep lose: $name | awk '{print $NF}';
|
||||
done |
|
||||
awk '{a[$1]++}END{for(i in a)print i,a[i]}' |
|
||||
sort -k2nr |
|
||||
pr -t -a -5 |
|
||||
sed ${lines}q
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
a=$(./rank results/$1 | awk 'NR<7 {print $2}')
|
||||
/bin/echo -n "$1 "
|
||||
./wavg $a
|
||||
@@ -0,0 +1,105 @@
|
||||
{
|
||||
"no_comment" : "mandatory comment: because comments were removed from the original JSON spec",
|
||||
"entry_JSON_format_version" : "1.2 2024-09-25",
|
||||
"award" : "Prize in bot talk",
|
||||
"year" : 2024,
|
||||
"dir" : "cable1",
|
||||
"entry_id" : "2024_cable1",
|
||||
"title" : "chatioccc",
|
||||
"abstract" : "LLM inference engine",
|
||||
"author_set" : [
|
||||
{
|
||||
"author_handle" : "Adrian_Cable"
|
||||
}
|
||||
],
|
||||
"manifest" : [
|
||||
{
|
||||
"file_path" : "prog.c",
|
||||
"inventory_order" : 20,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "c",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "entry source code"
|
||||
},
|
||||
{
|
||||
"file_path" : "Makefile",
|
||||
"inventory_order" : 30,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "makefile",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "entry Makefile"
|
||||
},
|
||||
{
|
||||
"file_path" : "prog.orig.c",
|
||||
"inventory_order" : 50,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "c",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "original source code"
|
||||
},
|
||||
{
|
||||
"file_path" : "get_model.sh",
|
||||
"inventory_order" : 100,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "tool to download llama2-7b-chat model"
|
||||
},
|
||||
{
|
||||
"file_path" : "try.sh",
|
||||
"inventory_order" : 100,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "script to try entry"
|
||||
},
|
||||
{
|
||||
"file_path" : "2024_cable1.tar.bz2",
|
||||
"inventory_order" : 1415926535,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "tbz2",
|
||||
"display_via_github" : false,
|
||||
"entry_text" : "download entry tarball"
|
||||
},
|
||||
{
|
||||
"file_path" : ".entry.json",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "json",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "entry summary and manifest in JSON"
|
||||
},
|
||||
{
|
||||
"file_path" : ".gitignore",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "gitignore",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "list of files that should not be committed under git"
|
||||
},
|
||||
{
|
||||
"file_path" : ".path",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "path",
|
||||
"display_via_github" : false,
|
||||
"entry_text" : "directory path from top level directory"
|
||||
},
|
||||
{
|
||||
"file_path" : "README.md",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "markdown",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "markdown source for this web page"
|
||||
},
|
||||
{
|
||||
"file_path" : "index.html",
|
||||
"inventory_order" : 4294967295,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "html",
|
||||
"display_via_github" : false,
|
||||
"entry_text" : "this web page"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
LLAMA2_LICENSE
|
||||
eeyore
|
||||
eeyore_openmp
|
||||
linux
|
||||
linux_openmp
|
||||
model
|
||||
openmp
|
||||
prog_openmp
|
||||
rainman
|
||||
rainman_openmp
|
||||
snoop
|
||||
snoop_openmp
|
||||
@@ -0,0 +1 @@
|
||||
2024/cable1
|
||||
Binary file not shown.
@@ -0,0 +1,257 @@
|
||||
#!/usr/bin/env make
|
||||
#
|
||||
# 2024/cable1
|
||||
|
||||
#############################
|
||||
# shell used by this Makefile
|
||||
#############################
|
||||
|
||||
SHELL= bash
|
||||
|
||||
|
||||
#######################
|
||||
# common tool locations
|
||||
#######################
|
||||
|
||||
include ../../var.mk
|
||||
|
||||
|
||||
#####################
|
||||
# C compiler settings
|
||||
#####################
|
||||
|
||||
# Common C compiler warnings to silence
|
||||
#
|
||||
# Example: CSILENCE= -Wno-poison-system-directories
|
||||
#
|
||||
CSILENCE= -Wno-deprecated-non-prototype -Wno-multichar -Wno-parentheses \
|
||||
-Wno-pointer-sign -Wno-return-type -Wno-misleading-indentation -Wno-unknown-pragmas
|
||||
|
||||
# Attempt to silence unknown warning options
|
||||
#
|
||||
CUNKNOWN= -Wno-unknown-warning-option
|
||||
|
||||
# Common C compiler warning flags
|
||||
#
|
||||
# NOTE: The addition of -pedantic to CWARN is a challenge that
|
||||
# You may wish to avoid if it proves too problematic.
|
||||
# There is NO penalty for removing -pedantic from CWARN.
|
||||
#
|
||||
CWARN= -Wall -Wextra ${CSILENCE} ${CUNKNOWN}
|
||||
|
||||
# Compiler standard
|
||||
#
|
||||
CSTD= -std=gnu17
|
||||
|
||||
# Compiler bit architecture
|
||||
#
|
||||
# Example for 32-bitness: ARCH= -m32
|
||||
# Example for 64-bitness: ARCH= -m64
|
||||
#
|
||||
# NOTE: Normally one should NOT specify a specific architecture.
|
||||
#
|
||||
ARCH=
|
||||
|
||||
# Defines that are needed to compile
|
||||
#
|
||||
# Example: -Dfoo -Dbar=baz
|
||||
#
|
||||
CDEFINE= -DM=\"model\"
|
||||
|
||||
# Include files that are needed to compile
|
||||
#
|
||||
# Example: CINCLUDE= -include stdio.h
|
||||
#
|
||||
CINCLUDE=
|
||||
|
||||
# Other flags to pass to the C compiler
|
||||
#
|
||||
# Example: COTHER= -fno-math-errno
|
||||
#
|
||||
COTHER= -ffast-math -fno-math-errno -march=native
|
||||
|
||||
# Optimization
|
||||
#
|
||||
# NOTE: Feel free to change the level of compiler optimization.
|
||||
# The "-O3" is just a friendly default you might wish to try.
|
||||
#
|
||||
# Example: OPT= -O0 -g
|
||||
#
|
||||
OPT= -O3
|
||||
|
||||
# Default flags for ANSI C compilation
|
||||
#
|
||||
CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${COTHER} ${OPT}
|
||||
|
||||
# Libraries needed to build
|
||||
#
|
||||
# Example: LDFLAGS= -lncurses -lm
|
||||
#
|
||||
LDFLAGS= -lm
|
||||
|
||||
# C compiler to use
|
||||
#
|
||||
# NOTE: The IOCCC Judges recommend you leave CC as just "cc"
|
||||
# and NOT set it to clang, or gcc, or something else
|
||||
# unless you have a STRONG reason to do so.
|
||||
#
|
||||
# Setting CC to something other than "cc" makes your
|
||||
# code less portable to those who do not have your
|
||||
# particular C compiler. **hint**
|
||||
#
|
||||
# If you want to test your code with a particular C compiler,
|
||||
# use the make command line. For example:
|
||||
#
|
||||
# make all CC=clang
|
||||
# make all CC=gcc
|
||||
#
|
||||
CC= cc
|
||||
|
||||
# Compiler add-ons or replacements for clang only
|
||||
#
|
||||
ifeq "$(findstring $(CLANG),${CC})" "$(CLANG)"
|
||||
#
|
||||
# NOTE: This code is only invoked when CC is "clang"
|
||||
# such as when you use the make command line:
|
||||
#
|
||||
# make all CC=clang
|
||||
#
|
||||
CSILENCE+= -Wno-c99-compat -Wno-comma -Wno-deprecated-non-prototype \
|
||||
-Wno-dollar-in-identifier-extension -Wno-double-promotion \
|
||||
-Wno-float-conversion -Wno-implicit-float-conversion \
|
||||
-Wno-missing-prototypes -Wno-missing-variable-declarations \
|
||||
-Wno-multichar -Wno-parentheses -Wno-pedantic -Wno-pointer-sign \
|
||||
-Wno-poison-system-directories -Wno-return-type -Wno-shadow \
|
||||
-Wno-sign-conversion -Wno-source-uses-openmp -Wno-strict-prototypes \
|
||||
-Wno-enum-float-conversion -Wno-reserved-identifier \
|
||||
-Wno-unsafe-buffer-usage
|
||||
#
|
||||
CWARN+= -Weverything
|
||||
#
|
||||
endif
|
||||
|
||||
# Specific add-ons or replacements for gcc only
|
||||
#
|
||||
ifeq "$(findstring $(GCC),${CC})" "$(GCC)"
|
||||
#
|
||||
# NOTE: This code is only invoked when CC is "gcc"
|
||||
# such as when you use the make command line:
|
||||
#
|
||||
# make all CC=gcc
|
||||
#
|
||||
CSILENCE+=
|
||||
#
|
||||
CWARN+=
|
||||
#
|
||||
endif
|
||||
|
||||
|
||||
###########################################
|
||||
# Special Makefile variables for this entry
|
||||
###########################################
|
||||
|
||||
ENTRY= prog
|
||||
PROG= ${ENTRY}
|
||||
#
|
||||
OBJ= ${PROG}.o
|
||||
TARGET= ${PROG} snoop eeyore linux rainman
|
||||
TARGET_MP= openmp snoop_openmp eeyore_openmp linux_openmp rainman_openmp
|
||||
#
|
||||
ALT_OBJ=
|
||||
ALT_TARGET=
|
||||
|
||||
# list any data files supplied with your submission
|
||||
#
|
||||
# Example: DATA= curds whey
|
||||
#
|
||||
DATA=
|
||||
|
||||
# system prompts for personalities
|
||||
#
|
||||
SNOOP= "You are Snoop Dogg."
|
||||
EEYORE= "You are Eeyore, always miserable, passive aggressive and self-deprecating."
|
||||
LINUX= "You are a Linux terminal. I will type a command, and you will print its output inside a single code block."
|
||||
RAINMAN= "You are the title character of the movie Rain Man."
|
||||
|
||||
#################
|
||||
# build the entry
|
||||
#################
|
||||
|
||||
all: data ${TARGET}
|
||||
@${TRUE}
|
||||
|
||||
.PHONY: all alt data everything clean clobber
|
||||
|
||||
# how to compile
|
||||
#
|
||||
${PROG}: ${PROG}.c
|
||||
${CC} ${CFLAGS} ${PROG}.c -DS='""' -o $@ ${LDFLAGS}
|
||||
|
||||
all_openmp: ${TARGET_MP}
|
||||
|
||||
openmp: prog_openmp
|
||||
${CP} -f $? $@
|
||||
|
||||
prog_openmp: ${PROG}.c
|
||||
${CC} ${CFLAGS} ${PROG}.c -fopenmp -DS='""' -o $@ ${LDFLAGS}
|
||||
|
||||
snoop: ${PROG}.c
|
||||
${CC} ${CFLAGS} ${PROG}.c -DS='${SNOOP}' -o $@ ${LDFLAGS}
|
||||
|
||||
snoop_openmp: ${PROG}.c
|
||||
${CC} ${CFLAGS} ${PROG}.c -fopenmp -DS='${SNOOP}' -o $@ ${LDFLAGS}
|
||||
|
||||
eeyore: ${PROG}.c
|
||||
${CC} ${CFLAGS} ${PROG}.c -DS='${EEYORE}' -o $@ ${LDFLAGS}
|
||||
|
||||
eeyore_openmp: ${PROG}.c
|
||||
${CC} ${CFLAGS} ${PROG}.c -fopenmp -DS='${EEYORE}' -o $@ ${LDFLAGS}
|
||||
|
||||
linux: ${PROG}.c
|
||||
${CC} ${CFLAGS} ${PROG}.c -DS='${LINUX}' -o $@ ${LDFLAGS}
|
||||
|
||||
linux_openmp: ${PROG}.c
|
||||
${CC} ${CFLAGS} ${PROG}.c -fopenmp -DS='${LINUX}' -o $@ ${LDFLAGS}
|
||||
|
||||
rainman: ${PROG}.c
|
||||
${CC} ${CFLAGS} ${PROG}.c -DS='${RAINMAN}' -o $@ ${LDFLAGS}
|
||||
|
||||
rainman_openmp: ${PROG}.c
|
||||
${CC} ${CFLAGS} ${PROG}.c -fopenmp -DS='${RAINMAN}' -o $@ ${LDFLAGS}
|
||||
|
||||
# alternative executable
|
||||
#
|
||||
alt: data ${ALT_TARGET}
|
||||
@${TRUE}
|
||||
|
||||
${PROG}.alt: ${PROG}.alt.c
|
||||
${CC} ${CFLAGS} ${PROG}.alt.c -o $@ ${LDFLAGS}
|
||||
|
||||
# data files
|
||||
#
|
||||
data: ${DATA}
|
||||
@${TRUE}
|
||||
|
||||
# both all and alt
|
||||
#
|
||||
everything: all alt
|
||||
@${TRUE}
|
||||
|
||||
|
||||
###############
|
||||
# utility rules
|
||||
###############
|
||||
#
|
||||
clean:
|
||||
${RM} -f ${OBJ} ${ALT_OBJ}
|
||||
|
||||
clobber: clean
|
||||
${RM} -f ${TARGET} ${ALT_TARGET} ${TARGET_MP} prog_openmp
|
||||
${RM} -rf *.dSYM
|
||||
|
||||
|
||||
######################################
|
||||
# optional include of 1337 hacker rulz
|
||||
######################################
|
||||
|
||||
-include 1337.mk ../1337.mk ../../1337.mk
|
||||
@@ -0,0 +1,245 @@
|
||||
## To build:
|
||||
|
||||
``` <!---sh-->
|
||||
make all
|
||||
|
||||
./get_model.sh
|
||||
```
|
||||
|
||||
**NOTE**: You must accept the license to run the program.
|
||||
|
||||
|
||||
## To use:
|
||||
|
||||
**NOTE**: You must have successful run the
|
||||
[2024/cable1/get_model.sh](%%REPO_URL%%/2024/cable1/get_model.sh) script
|
||||
before running the program.
|
||||
|
||||
``` <!---sh-->
|
||||
./prog
|
||||
```
|
||||
|
||||
|
||||
## Try:
|
||||
|
||||
``` <!---sh-->
|
||||
echo 'Describe yourself.' | ./prog
|
||||
|
||||
echo 'Describe yourself.' | ./linux
|
||||
|
||||
echo 'ls' | ./linux
|
||||
|
||||
echo 'Describe yourself.' | ./eeyore
|
||||
|
||||
echo 'Why are you so sad?' | ./eeyore
|
||||
|
||||
echo 'Describe yourself.' | ./snoop
|
||||
|
||||
echo 'Tell me a silly joke.' | ./snoop
|
||||
|
||||
echo 'Describe yourself.' | ./rainman
|
||||
|
||||
echo 'How 2+2 can equal 5?' | ./rainman
|
||||
```
|
||||
|
||||
|
||||
### Fun things to try
|
||||
|
||||
Here are some fun things give as input:
|
||||
|
||||
> Why did this entry win IOCCC28?
|
||||
|
||||
> Translate "Plurima responsa non recta esse supponamus"
|
||||
|
||||
> Write a C program that writes a C program.
|
||||
|
||||
> Write a sentence so that contains a split infinitive.
|
||||
|
||||
> Rewrite the previous sentence so that it ends in a preposition.
|
||||
|
||||
> How much wood does a woodchuck?
|
||||
|
||||
> Tell me a silly joke.
|
||||
|
||||
> Write a poem about a poet who is illiterate.
|
||||
|
||||
> Give examples, based on mathematics, where 2+2 can equal 5.
|
||||
|
||||
Please note that the quality and accuracy of the answers you receive may vary. :-)
|
||||
We do **NOT** recommend believing everything you read from this program.
|
||||
**Caveat lector!**
|
||||
|
||||
|
||||
## Alternate code:
|
||||
|
||||
|
||||
### Alternate build:
|
||||
|
||||
**NOTE**: You must have successful run the
|
||||
[2024/cable1/get_model.sh](%%REPO_URL%%/2024/cable1/get_model.sh) script
|
||||
before running the program.
|
||||
|
||||
``` <!---sh-->
|
||||
make openmp
|
||||
```
|
||||
|
||||
|
||||
### Alternate use:
|
||||
|
||||
``` <!---sh-->
|
||||
./prog_openmp
|
||||
```
|
||||
|
||||
|
||||
## Judges' remarks:
|
||||
|
||||
This entry may benefit from OpenMP (via `prog_openmp`) for platforms that
|
||||
support compiling with OpenMP. Even on a cheap 8-core laptop, the produces
|
||||
tokens with a tolerable speed, at least for the first few lines.
|
||||
Without OpenMP, one must patiently await answers.
|
||||
|
||||
To preserve this entry for posterity, one thing to explore is to find the
|
||||
minimal model which exhibits a sensible behavior: for example, printing
|
||||
"Hello, world!" as the response to any input.
|
||||
|
||||
We took the liberty of making the program terminate gracefully at the end
|
||||
of input, at the cost of 2 extra bytes, and preserving the original in
|
||||
`prog.orig.c`.
|
||||
|
||||
**NOTE**: Even with OpenMP, this tool is not the fastest. A mild level of patience is advised.
|
||||
|
||||
**DISCLAIMER**: _riPlurima responsa non recta esse supponamus_!
|
||||
|
||||
|
||||
### IMPORTANT Download
|
||||
|
||||
ChatIOCCC runs Meta's open source `llama2-7b-chat` model. Before using ChatIOCCC, you'll need to accept Meta's license
|
||||
and download the model weights (~7GB):
|
||||
|
||||
``` <!---sh-->
|
||||
./get_model.sh
|
||||
```
|
||||
|
||||
|
||||
## Author's remarks:
|
||||
|
||||
ChatIOCCC - the world's smallest and best LLM inference engine
|
||||
|
||||
|
||||
### About
|
||||
|
||||
ChatIOCCC is the world's smallest LLM (large language model) inference engine - a "generative AI chatbot" in
|
||||
plain-speak. ChatIOCCC runs a modern open-source model (Meta's LLaMA 2 with 7 billion parameters) and has a
|
||||
good knowledge of the world, can understand and speak multiple languages, write code, and many other things. Aside from
|
||||
the model weights, it has no external dependencies and will run on any 64-bit platform with enough RAM.
|
||||
|
||||
LLM inference engines are extremely complex, incorporating a tokenizer (SentencePiece or byte-pair encoding), embedding layer,
|
||||
transformer layers (including multi-head self-attention, feed-forward neural network, activation, layer norm and
|
||||
residual connections), key/value caching for performance, output projection, decoding, and a state machine to control
|
||||
the data flow. Implementing all of that machinery, with no external dependencies, generally takes thousands or tens of
|
||||
thousands of lines of code. ChatIOCCC is a full LLM implementation in under 1800 bytes of C, and even supports
|
||||
UTF-8/Unicode input and output and parallel processing over multiple CPU cores via OpenMP.
|
||||
|
||||
The author was inspired by [llama2.c](https://github.com/karpathy/llama2.c) which aims to foster understanding of how LLMs work via a simple
|
||||
implementation. Unfortunately, even AI experts don't actually understand why LLMs work at all. This core truth led to
|
||||
an epiphany: as LLMs are already maximally incomprehensible, obfuscation cannot make them more so. So, in the spirit of
|
||||
the IOCCC we can set aside the futility of aiming for comprehensibility, and instead focus purely on size.
|
||||
|
||||
Since smaller is always better, and ChatIOCCC is the world's smallest LLM inference engine, it is therefore also the
|
||||
world's best LLM inference engine.
|
||||
|
||||
Whether or not you fail to disagree that this paragraph, and those above, are or are not in and of themselves maximally
|
||||
incomprehensible, they represent in either case the origin story of this IOCCC submission, which implements an LLM
|
||||
inference engine in an impossibly minimal quantity of maximally incomprehensible C code.
|
||||
|
||||
|
||||
### Requirements
|
||||
|
||||
In addition to using `./get_model.sh` to download the `llama2-7b-chat` model (see above), you'll need around 11GB of free RAM to run ChatIOCCC.
|
||||
|
||||
|
||||
### Fun things to ask
|
||||
|
||||
Here are some fun things you can ask ChatIOCCC to do for you:
|
||||
|
||||
> Tell me a surprising fact about an animal of your choice.
|
||||
|
||||
> Write a short story for a 5 year old girl, featuring Sobieski the dog and Pepe the cat.
|
||||
|
||||
> Write a C program which sorts a list using the bubble sort algorithm.
|
||||
|
||||
> Write a poem about a little boy who builds a rocket to fly to the moon. In Japanese, please.
|
||||
|
||||
> Translate into English: 这个项目会成为 2024 年 IOCCC 的赢家吗?
|
||||
|
||||
> Tell me about the IOCCC and its history. Then, write a poem in French about it.
|
||||
|
||||
|
||||
### Personalities
|
||||
|
||||
ChatIOCCC allows the LLM's system prompt to be defined at compile time (by using `-DS="prompt..."`).
|
||||
The supplied `Makefile` includes three example personalities (set via system prompts) you can try: `eeyore`, `snoop` and `linux` (and
|
||||
their OpenMP versions, `eeyore_openmp`, `snoop_openmp`, `linux_openmp`).
|
||||
The `eeyore` and `snoop` personalities are self-explanatory. The `linux` personality makes ChatIOCCC act like a Linux
|
||||
machine. Try for example:
|
||||
|
||||
``` <!---sh-->
|
||||
make linux
|
||||
./linux
|
||||
```
|
||||
|
||||
Or for much better performance:
|
||||
|
||||
``` <!---sh-->
|
||||
make linux_openmp
|
||||
./linux_openmp
|
||||
```
|
||||
|
||||
Then try typing some Linux commands. You can even run an imaginary C compiler inside the LLM:
|
||||
|
||||
``` <!---sh-->
|
||||
pwd
|
||||
cat /etc/passwd
|
||||
echo 'int main() { for (int i = 1; i <= 10; i++) printf("IOCCC %d\n", i); }' > test.c; gcc test.c; ./a.out
|
||||
ls -la a.out
|
||||
```
|
||||
|
||||
|
||||
### Limitations
|
||||
|
||||
The `llama2-7b-chat` model has a context window of 4096 tokens (around 2000 words). As you use
|
||||
ChatIOCCC, the context window fills up from your prompts and from the model's responses,
|
||||
and the model gets progressively slower due to the attention mechanism needing to do more work. This is normal.
|
||||
|
||||
When the context window is full, ChatIOCCC will clear it and at that point the model will
|
||||
'forget' prompts/responses from earlier in the session. Various more sophisticated techniques
|
||||
exist to handle context window overflow (summarization, rolling window, NTK-aware scaled RoPE etc.), the implementation
|
||||
of which is left to the reader with too much time on his/her hands.
|
||||
|
||||
|
||||
### Footnotes
|
||||
|
||||
The length of this entry's source code is 1750 bytes. Many interesting things happened in 1750, including:
|
||||
|
||||
- The Industrial Revolution begins in Great Britain
|
||||
- British astronomer Thomas Wright first proposes that the Milky Way is a disk-shaped system of stars, with our Solar System near its center
|
||||
- Benjamin Franklin first proposes the idea that lightning is electrical in nature
|
||||
- Adwaita the giant tortoise, who lived until 2006, is born
|
||||
- Johann Sebastian Bach dies
|
||||
|
||||
As a final note, the author is pleased to report that this entry is [absolutely totally impossible](https://chatgpt.com/share/6839d275-c644-8004-9301-0ea781d8f5aa) according to ChatGPT. But, to quote Walt Disney, "it's kind of fun to do the impossible".
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
Copyright © 1984-2025 by Landon Curt Noll and Leonid A. Broukhis. All Rights Reserved.
|
||||
|
||||
You are free to share and adapt this file under the terms of this license:
|
||||
|
||||
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
||||
|
||||
For more information, see:
|
||||
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
-->
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
LICENSE_URL="https://od.lk/d/NTJfNDgwODA2NjVf/LLAMA2_LICENSE"
|
||||
MODEL_LOCATION_URL="https://od.lk/d/NTJfNDgxMDQzMzNf/model_location"
|
||||
|
||||
# Step 1: Download and display the license file
|
||||
|
||||
wget -q -O LLAMA2_LICENSE "$LICENSE_URL"
|
||||
|
||||
cat LLAMA2_LICENSE
|
||||
echo ""
|
||||
echo ""
|
||||
echo "----------------"
|
||||
echo ""
|
||||
|
||||
# Step 2: Ask user to accept the license, then download the model
|
||||
|
||||
read -r -p "Accept Meta's license to download the llama2-7b-chat model for use with ChatIOCCC. Type Y to accept: " ACCEPT
|
||||
|
||||
if [[ "$ACCEPT" == "Y" || "$ACCEPT" == "y" || "$ACCEPT" == "yes" || "$ACCEPT" == "Yes" || "$ACCEPT" == "YES" ]]; then
|
||||
# Step 3: Download the model file
|
||||
echo ""
|
||||
echo "Downloading model ..."
|
||||
rm -f LLAMA2_LICENSE model
|
||||
wget -q --show-progress -O model "$(wget -q -O - "$MODEL_LOCATION_URL")"
|
||||
else
|
||||
echo "License not accepted. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
@@ -0,0 +1,756 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<!-- START: two lines up starts content from: inc/top.default.html -->
|
||||
|
||||
<!-- END: this line ends content from: inc/top.default.html -->
|
||||
<!-- START: this line starts content from: inc/head.default.html -->
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../ioccc.css">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@100..900&display=swap" rel="stylesheet">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
<title>2024/cable1 - Prize in bot talk</title>
|
||||
<link rel="icon" type="image/x-icon" href="../../favicon.ico">
|
||||
<meta name="description" content="2024 IOCCC entry cable1 - Prize in bot talk">
|
||||
<meta name="keywords" content="IOCCC, 2024, IOCCC 2024, IOCCC entry, cable1, Prize in bot talk">
|
||||
</head>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
|
||||
<!-- END: this line ends content from: inc/head.default.html -->
|
||||
|
||||
<!-- -->
|
||||
<!-- This web page was formed via the tool: bin/readme2index.sh -->
|
||||
<!-- The content of main section of this web page came from: 2024/cable1/README.md -->
|
||||
<!-- -->
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<!-- !!! Do not modify this web page, instead modify the file: 2024/cable1/README.md !!! -->
|
||||
<!-- !!! Do not modify this web page, instead modify the file: 2024/cable1/README.md !!! -->
|
||||
<!-- !!! Do not modify this web page, instead modify the file: 2024/cable1/README.md !!! -->
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
|
||||
<!-- Markdown content was converted into HTML via the tool: bin/md2html.sh -->
|
||||
|
||||
<!-- START: this line starts content from: inc/body.default.html -->
|
||||
|
||||
<body>
|
||||
|
||||
<!-- END: this line ends content from: inc/body.default.html -->
|
||||
<!-- START: this line starts content from: inc/topbar.default.html -->
|
||||
|
||||
<div class="theader">
|
||||
<nav class="topbar">
|
||||
<div class="container">
|
||||
<div class="logo">
|
||||
<a href="../../index.html" class="logo-link">
|
||||
IOCCC
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="topbar-items">
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
Entries
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../years.html" class="sub-item-link">
|
||||
Winning entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../authors.html" class="sub-item-link">
|
||||
Winning authors
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../location.html" class="sub-item-link">
|
||||
Location of authors
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../bugs.html" class="sub-item-link">
|
||||
Bugs and (mis)features
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#fix_an_entry" class="sub-item-link">
|
||||
Fixing entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#fix_author" class="sub-item-link">
|
||||
Updating author info
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
Status
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../news.html" class="sub-item-link">
|
||||
News
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../status.html" class="sub-item-link">
|
||||
Contest status
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../next/rules.html" class="sub-item-link">
|
||||
IOCCC rules
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../next/guidelines.html" class="sub-item-link">
|
||||
IOCCC guidelines
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../markdown.html" class="sub-item-link">
|
||||
Markdown guidelines
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../SECURITY.html" class="sub-item-link">
|
||||
Security policy
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
FAQ
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html" class="sub-item-link">
|
||||
Frequently asked questions
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../quick-start.html#enter" class="sub-item-link">
|
||||
Enter the IOCCC
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#compiling" class="sub-item-link">
|
||||
Compiling entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#running_entries" class="sub-item-link">
|
||||
Running entries
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../faq.html#help" class="sub-item-link">
|
||||
How to help
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<span class="item-header">
|
||||
About
|
||||
</span>
|
||||
|
||||
<div class="sub-item">
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../index.html" class="sub-item-link">
|
||||
Home page
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../social.html" class="sub-item-link">
|
||||
IOCCC social media
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../about.html" class="sub-item-link">
|
||||
About the IOCCC
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../judges.html" class="sub-item-link">
|
||||
The judges
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../thanks-for-help.html" class="sub-item-link">
|
||||
Thanks for the help
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="outfit-font">
|
||||
<a href="../../contact.html" class="sub-item-link">
|
||||
Contact us
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="header-mobile-menu">
|
||||
<noscript>
|
||||
<a href="../../nojs-menu.html" class="topbar-js-label">
|
||||
Please Enable JavaScript
|
||||
</a>
|
||||
</noscript>
|
||||
|
||||
<button id="header-open-menu-button" class="topbar-mobile-menu">
|
||||
<img
|
||||
src="../../png/hamburger-icon-open.png"
|
||||
alt="hamburger style menu icon - open state"
|
||||
width=48
|
||||
height=48>
|
||||
</button>
|
||||
|
||||
<button id="header-close-menu-button" class="hide-content">
|
||||
<img
|
||||
src="../../png/hamburger-icon-closed.png"
|
||||
alt="hamburger style menu icon - closed state"
|
||||
width=48
|
||||
height=48>
|
||||
</button>
|
||||
|
||||
<div id="mobile-menu-panel" class="hide-content">
|
||||
<div class="mobile-menu-container">
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
<div class="mobile-menu-item">
|
||||
Entries
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../years.html">
|
||||
Winning entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../authors.html">
|
||||
Winning authors
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../location.html">
|
||||
Location of authors
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../bugs.html">
|
||||
Bugs and (mis)features
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#fix_an_entry">
|
||||
Fixing entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#fix_author">
|
||||
Updating author info
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../thanks-for-help.html">
|
||||
Thanks for the help
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
|
||||
<div class="mobile-menu-item">
|
||||
Status
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../news.html">
|
||||
News
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../status.html">
|
||||
Contest status
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../next/rules.html">
|
||||
IOCCC rules
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../next/guidelines.html">
|
||||
IOCCC guidelines
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../markdown.html">
|
||||
Markdown guidelines
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../SECURITY.html">
|
||||
Security policy
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
<div class="mobile-menu-item">
|
||||
FAQ
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html">
|
||||
Frequently asked questions
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../quick-start.html#enter">
|
||||
Enter the IOCCC
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#compiling">
|
||||
Compiling entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#running_entries">
|
||||
Running entries
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../faq.html#help">
|
||||
How to help
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mobile-menu-wrapper">
|
||||
<div class="mobile-menu-item">
|
||||
About
|
||||
</div>
|
||||
<div class="mobile-submenu-wrapper">
|
||||
|
||||
<a class="mobile-submenu-item" href="../../index.html">
|
||||
Home page
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../social.html">
|
||||
IOCCC social media
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../about.html">
|
||||
About the IOCCC
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../judges.html">
|
||||
The judges
|
||||
</a>
|
||||
|
||||
<a class="mobile-submenu-item" href="../../contact.html">
|
||||
Contact us
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var headerOpenMenuButton = document.getElementById("header-open-menu-button");
|
||||
var headerCloseMenuButton = document.getElementById("header-close-menu-button");
|
||||
var mobileMenuPanel = document.getElementById("mobile-menu-panel");
|
||||
|
||||
headerOpenMenuButton.addEventListener("click", () => {
|
||||
headerOpenMenuButton.classList.remove("topbar-mobile-menu");
|
||||
headerOpenMenuButton.classList.add("hide-content");
|
||||
|
||||
headerCloseMenuButton.classList.remove("hide-content");
|
||||
headerCloseMenuButton.classList.add("topbar-mobile-menu");
|
||||
|
||||
mobileMenuPanel.classList.remove("hide-content");
|
||||
mobileMenuPanel.classList.add("topbar-mobile-panel");
|
||||
});
|
||||
|
||||
headerCloseMenuButton.addEventListener("click", () => {
|
||||
headerCloseMenuButton.classList.remove("topbar-mobile-menu");
|
||||
headerCloseMenuButton.classList.add("hide-content");
|
||||
|
||||
mobileMenuPanel.classList.add("hide-content");
|
||||
mobileMenuPanel.classList.remove("topbar-mobile-panel");
|
||||
|
||||
headerOpenMenuButton.classList.add("topbar-mobile-menu");
|
||||
headerOpenMenuButton.classList.remove("hide-content");
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- END: this line ends content from: inc/topbar.default.html -->
|
||||
<!-- START: this line starts content from: inc/header.default.html -->
|
||||
|
||||
<div class="header">
|
||||
<a href="../../2011/zucker/index.html">
|
||||
<img src="../../png/ioccc.png"
|
||||
alt="IOCCC image by Matt Zucker"
|
||||
width=300
|
||||
height=110>
|
||||
</a>
|
||||
<h1>The International Obfuscated C Code Contest</h1>
|
||||
<h2>2024/cable1 - Prize in bot talk</h2>
|
||||
<h3>LLM inference engine</h3>
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/header.default.html -->
|
||||
<!-- START: this line starts content from: inc/navbar.mid.html -->
|
||||
|
||||
<div class="navbar">
|
||||
<a class="Left" href="../burton/index.html">← 2024/burton</a>
|
||||
<a class="Left" href="../index.html">↑ 2024 ↑</a>
|
||||
<a class="Left" href="../cable2/index.html">2024/cable2 →</a>
|
||||
<a class="Right" href="https://github.com/ioccc-src/winner/blob/master/2024/cable1/prog.c">C code</a>
|
||||
<a class="Right" href="https://github.com/ioccc-src/winner/blob/master/2024/cable1/Makefile">Makefile</a>
|
||||
<a class="Right" href="#inventory">Inventory</a>
|
||||
<a class="Right" href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fwww.ioccc.org%2F2024%2Fcable1%2Findex.html">✓</a>
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/navbar.mid.html -->
|
||||
<!-- START: this line starts content from: inc/before-content.default.html -->
|
||||
|
||||
<div class="content" id="content">
|
||||
|
||||
<!-- END: this line ends content from: inc/before-content.default.html -->
|
||||
<!-- START: this line starts content for HTML phase 20 by: bin/output-index-author.sh via bin/md2html.sh -->
|
||||
|
||||
<!-- START: this line starts content generated by: bin/output-index-author.sh -->
|
||||
|
||||
<h2 id="author">Author:</h2>
|
||||
<ul>
|
||||
<li>Name: <a href="../../authors.html#Adrian_Cable">Adrian Cable</a><br>
|
||||
Location: <a href="../../location.html#US">US</a> - <em>United States of America</em> (<em>United States</em>)</li>
|
||||
</ul>
|
||||
|
||||
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
|
||||
|
||||
<!-- END: this line ends content for HTML phase 20 by: bin/output-index-author.sh via bin/md2html.sh -->
|
||||
<!-- START: this line starts content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||||
|
||||
<!-- BEFORE: 1st line of markdown file: 2024/cable1/README.md -->
|
||||
<h2 id="to-build">To build:</h2>
|
||||
<pre><code> make all
|
||||
|
||||
./get_model.sh</code></pre>
|
||||
<p><strong>NOTE</strong>: You must accept the license to run the program.</p>
|
||||
<h2 id="to-use">To use:</h2>
|
||||
<p><strong>NOTE</strong>: You must have successful run the
|
||||
<a href="https://github.com/ioccc-src/winner/blob/master/2024/cable1/get_model.sh">2024/cable1/get_model.sh</a> script
|
||||
before running the program.</p>
|
||||
<pre><code> ./prog</code></pre>
|
||||
<h2 id="try">Try:</h2>
|
||||
<pre><code> echo 'Describe yourself.' | ./prog
|
||||
|
||||
echo 'Describe yourself.' | ./linux
|
||||
|
||||
echo 'ls' | ./linux
|
||||
|
||||
echo 'Describe yourself.' | ./eeyore
|
||||
|
||||
echo 'Why are you so sad?' | ./eeyore
|
||||
|
||||
echo 'Describe yourself.' | ./snoop
|
||||
|
||||
echo 'Tell me a silly joke.' | ./snoop
|
||||
|
||||
echo 'Describe yourself.' | ./rainman
|
||||
|
||||
echo 'How 2+2 can equal 5?' | ./rainman</code></pre>
|
||||
<h3 id="fun-things-to-try">Fun things to try</h3>
|
||||
<p>Here are some fun things give as input:</p>
|
||||
<blockquote>
|
||||
<p>Why did this entry win IOCCC28?</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Translate “Plurima responsa non recta esse supponamus”</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Write a C program that writes a C program.</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Write a sentence so that contains a split infinitive.</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Rewrite the previous sentence so that it ends in a preposition.</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>How much wood does a woodchuck?</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Tell me a silly joke.</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Write a poem about a poet who is illiterate.</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Give examples, based on mathematics, where 2+2 can equal 5.</p>
|
||||
</blockquote>
|
||||
<p>Please note that the quality and accuracy of the answers you receive may vary. :-)
|
||||
We do <strong>NOT</strong> recommend believing everything you read from this program.
|
||||
<strong>Caveat lector!</strong></p>
|
||||
<h2 id="alternate-code">Alternate code:</h2>
|
||||
<h3 id="alternate-build">Alternate build:</h3>
|
||||
<p><strong>NOTE</strong>: You must have successful run the
|
||||
<a href="https://github.com/ioccc-src/winner/blob/master/2024/cable1/get_model.sh">2024/cable1/get_model.sh</a> script
|
||||
before running the program.</p>
|
||||
<pre><code> make openmp</code></pre>
|
||||
<h3 id="alternate-use">Alternate use:</h3>
|
||||
<pre><code> ./prog_openmp</code></pre>
|
||||
<h2 id="judges-remarks">Judges’ remarks:</h2>
|
||||
<p>This entry may benefit from OpenMP (via <code>prog_openmp</code>) for platforms that
|
||||
support compiling with OpenMP. Even on a cheap 8-core laptop, the produces
|
||||
tokens with a tolerable speed, at least for the first few lines.
|
||||
Without OpenMP, one must patiently await answers.</p>
|
||||
<p>To preserve this entry for posterity, one thing to explore is to find the
|
||||
minimal model which exhibits a sensible behavior: for example, printing
|
||||
“Hello, world!” as the response to any input.</p>
|
||||
<p>We took the liberty of making the program terminate gracefully at the end
|
||||
of input, at the cost of 2 extra bytes, and preserving the original in
|
||||
<code>prog.orig.c</code>.</p>
|
||||
<p><strong>NOTE</strong>: Even with OpenMP, this tool is not the fastest. A mild level of patience is advised.</p>
|
||||
<p><strong>DISCLAIMER</strong>: <em>riPlurima responsa non recta esse supponamus</em>!</p>
|
||||
<h3 id="important-download">IMPORTANT Download</h3>
|
||||
<p>ChatIOCCC runs Meta’s open source <code>llama2-7b-chat</code> model. Before using ChatIOCCC, you’ll need to accept Meta’s license
|
||||
and download the model weights (~7GB):</p>
|
||||
<pre><code> ./get_model.sh</code></pre>
|
||||
<h2 id="authors-remarks">Author’s remarks:</h2>
|
||||
<p>ChatIOCCC - the world’s smallest and best LLM inference engine</p>
|
||||
<h3 id="about">About</h3>
|
||||
<p>ChatIOCCC is the world’s smallest LLM (large language model) inference engine - a “generative AI chatbot” in
|
||||
plain-speak. ChatIOCCC runs a modern open-source model (Meta’s LLaMA 2 with 7 billion parameters) and has a
|
||||
good knowledge of the world, can understand and speak multiple languages, write code, and many other things. Aside from
|
||||
the model weights, it has no external dependencies and will run on any 64-bit platform with enough RAM.</p>
|
||||
<p>LLM inference engines are extremely complex, incorporating a tokenizer (SentencePiece or byte-pair encoding), embedding layer,
|
||||
transformer layers (including multi-head self-attention, feed-forward neural network, activation, layer norm and
|
||||
residual connections), key/value caching for performance, output projection, decoding, and a state machine to control
|
||||
the data flow. Implementing all of that machinery, with no external dependencies, generally takes thousands or tens of
|
||||
thousands of lines of code. ChatIOCCC is a full LLM implementation in under 1800 bytes of C, and even supports
|
||||
UTF-8/Unicode input and output and parallel processing over multiple CPU cores via OpenMP.</p>
|
||||
<p>The author was inspired by <a href="https://github.com/karpathy/llama2.c">llama2.c</a> which aims to foster understanding of how LLMs work via a simple
|
||||
implementation. Unfortunately, even AI experts don’t actually understand why LLMs work at all. This core truth led to
|
||||
an epiphany: as LLMs are already maximally incomprehensible, obfuscation cannot make them more so. So, in the spirit of
|
||||
the IOCCC we can set aside the futility of aiming for comprehensibility, and instead focus purely on size.</p>
|
||||
<p>Since smaller is always better, and ChatIOCCC is the world’s smallest LLM inference engine, it is therefore also the
|
||||
world’s best LLM inference engine.</p>
|
||||
<p>Whether or not you fail to disagree that this paragraph, and those above, are or are not in and of themselves maximally
|
||||
incomprehensible, they represent in either case the origin story of this IOCCC submission, which implements an LLM
|
||||
inference engine in an impossibly minimal quantity of maximally incomprehensible C code.</p>
|
||||
<h3 id="requirements">Requirements</h3>
|
||||
<p>In addition to using <code>./get_model.sh</code> to download the <code>llama2-7b-chat</code> model (see above), you’ll need around 11GB of free RAM to run ChatIOCCC.</p>
|
||||
<h3 id="fun-things-to-ask">Fun things to ask</h3>
|
||||
<p>Here are some fun things you can ask ChatIOCCC to do for you:</p>
|
||||
<blockquote>
|
||||
<p>Tell me a surprising fact about an animal of your choice.</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Write a short story for a 5 year old girl, featuring Sobieski the dog and Pepe the cat.</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Write a C program which sorts a list using the bubble sort algorithm.</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Write a poem about a little boy who builds a rocket to fly to the moon. In Japanese, please.</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Translate into English: 这个项目会成为 2024 年 IOCCC 的赢家吗?</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Tell me about the IOCCC and its history. Then, write a poem in French about it.</p>
|
||||
</blockquote>
|
||||
<h3 id="personalities">Personalities</h3>
|
||||
<p>ChatIOCCC allows the LLM’s system prompt to be defined at compile time (by using <code>-DS="prompt..."</code>).
|
||||
The supplied <code>Makefile</code> includes three example personalities (set via system prompts) you can try: <code>eeyore</code>, <code>snoop</code> and <code>linux</code> (and
|
||||
their OpenMP versions, <code>eeyore_openmp</code>, <code>snoop_openmp</code>, <code>linux_openmp</code>).
|
||||
The <code>eeyore</code> and <code>snoop</code> personalities are self-explanatory. The <code>linux</code> personality makes ChatIOCCC act like a Linux
|
||||
machine. Try for example:</p>
|
||||
<pre><code> make linux
|
||||
./linux</code></pre>
|
||||
<p>Or for much better performance:</p>
|
||||
<pre><code> make linux_openmp
|
||||
./linux_openmp</code></pre>
|
||||
<p>Then try typing some Linux commands. You can even run an imaginary C compiler inside the LLM:</p>
|
||||
<pre><code> pwd
|
||||
cat /etc/passwd
|
||||
echo 'int main() { for (int i = 1; i <= 10; i++) printf("IOCCC %d\n", i); }' > test.c; gcc test.c; ./a.out
|
||||
ls -la a.out</code></pre>
|
||||
<h3 id="limitations">Limitations</h3>
|
||||
<p>The <code>llama2-7b-chat</code> model has a context window of 4096 tokens (around 2000 words). As you use
|
||||
ChatIOCCC, the context window fills up from your prompts and from the model’s responses,
|
||||
and the model gets progressively slower due to the attention mechanism needing to do more work. This is normal.</p>
|
||||
<p>When the context window is full, ChatIOCCC will clear it and at that point the model will
|
||||
‘forget’ prompts/responses from earlier in the session. Various more sophisticated techniques
|
||||
exist to handle context window overflow (summarization, rolling window, NTK-aware scaled RoPE etc.), the implementation
|
||||
of which is left to the reader with too much time on his/her hands.</p>
|
||||
<h3 id="footnotes">Footnotes</h3>
|
||||
<p>The length of this entry’s source code is 1750 bytes. Many interesting things happened in 1750, including:</p>
|
||||
<ul>
|
||||
<li>The Industrial Revolution begins in Great Britain</li>
|
||||
<li>British astronomer Thomas Wright first proposes that the Milky Way is a disk-shaped system of stars, with our Solar System near its center</li>
|
||||
<li>Benjamin Franklin first proposes the idea that lightning is electrical in nature</li>
|
||||
<li>Adwaita the giant tortoise, who lived until 2006, is born</li>
|
||||
<li>Johann Sebastian Bach dies</li>
|
||||
</ul>
|
||||
<p>As a final note, the author is pleased to report that this entry is <a href="https://chatgpt.com/share/6839d275-c644-8004-9301-0ea781d8f5aa">absolutely totally impossible</a> according to ChatGPT. But, to quote Walt Disney, “it’s kind of fun to do the impossible”.</p>
|
||||
<!--
|
||||
|
||||
Copyright © 1984-2025 by Landon Curt Noll and Leonid A. Broukhis. All Rights Reserved.
|
||||
|
||||
You are free to share and adapt this file under the terms of this license:
|
||||
|
||||
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
||||
|
||||
For more information, see:
|
||||
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
-->
|
||||
<!-- AFTER: last line of markdown file: 2024/cable1/README.md -->
|
||||
|
||||
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||||
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
|
||||
|
||||
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
|
||||
|
||||
<div id="inventory">
|
||||
<h1 id="inventory-for-2024cable1">Inventory for 2024/cable1</h1>
|
||||
</div>
|
||||
<h2 id="primary-files">Primary files</h2>
|
||||
<ul>
|
||||
<li><a href="https://github.com/ioccc-src/winner/blob/master/2024/cable1/prog.c">prog.c</a> - entry source code</li>
|
||||
<li><a href="https://github.com/ioccc-src/winner/blob/master/2024/cable1/Makefile">Makefile</a> - entry Makefile</li>
|
||||
<li><a href="https://github.com/ioccc-src/winner/blob/master/2024/cable1/prog.orig.c">prog.orig.c</a> - original source code</li>
|
||||
<li><a href="https://github.com/ioccc-src/winner/blob/master/2024/cable1/get_model.sh">get_model.sh</a> - tool to download llama2-7b-chat model</li>
|
||||
<li><a href="https://github.com/ioccc-src/winner/blob/master/2024/cable1/try.sh">try.sh</a> - script to try entry</li>
|
||||
</ul>
|
||||
<h2 id="secondary-files">Secondary files</h2>
|
||||
<ul>
|
||||
<li><a href="2024_cable1.tar.bz2">2024_cable1.tar.bz2</a> - download entry tarball</li>
|
||||
<li><a href="https://github.com/ioccc-src/winner/blob/master/2024/cable1/README.md">README.md</a> - markdown source for this web page</li>
|
||||
<li><a href="https://github.com/ioccc-src/winner/blob/master/2024/cable1/.entry.json">.entry.json</a> - entry summary and manifest in JSON</li>
|
||||
<li><a href="https://github.com/ioccc-src/winner/blob/master/2024/cable1/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
|
||||
<li><a href=".path">.path</a> - directory path from top level directory</li>
|
||||
<li><a href="index.html">index.html</a> - this web page</li>
|
||||
</ul>
|
||||
<hr style="width:10%;text-align:left;margin-left:0">
|
||||
<h4>
|
||||
Jump to: <a href="#">top</a>
|
||||
</h4>
|
||||
|
||||
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
|
||||
|
||||
<!-- END: this line ends content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
|
||||
<!-- START: this line starts content from: inc/after-content.default.html -->
|
||||
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/after-content.default.html -->
|
||||
<!-- START: this line starts content from: inc/footer.inventory.html -->
|
||||
|
||||
<!--
|
||||
|
||||
Copyright © 1984-2025 by Landon Curt Noll. All Rights Reserved.
|
||||
|
||||
You are free to share and adapt this file under the terms of this license:
|
||||
|
||||
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
||||
|
||||
For more information, see:
|
||||
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
-->
|
||||
|
||||
<div class="footer">
|
||||
|
||||
<div id="copyright"><h3>Copyright © 1984-2025 by Landon Curt Noll:
|
||||
<a href="https://creativecommons.org/faq/#what-does-some-rights-reserved-mean"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer">Some Rights Reserved</a></h3>
|
||||
<p>
|
||||
This work is <b>licensed by Landon Curt Noll</b> under
|
||||
<b><a href="https://creativecommons.org/licenses/by-sa/4.0/?ref=chooser-v1"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer"
|
||||
style="display:inline-block;">CC BY-SA 4.0</a></b>.
|
||||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||||
src="../../png/cc.png"
|
||||
alt="cc inside circle symbol">
|
||||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||||
src="../../png/by.png"
|
||||
alt="person inside circle symbol">
|
||||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||||
src="../../png/sa.png"
|
||||
alt="arrow looping back on itself inside circle symbol"><br>
|
||||
You should <b>carefully review</b> the
|
||||
<b><a href="https://creativecommons.org/licenses/by-sa/4.0/legalcode.en"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer">CC BY-SA 4.0 LEGAL CODE</a></b>
|
||||
before using the licensed material.<br>
|
||||
You may wish to review the
|
||||
<b><a href="../../license.html"
|
||||
target="_blank"
|
||||
rel="license noopener noreferrer">highlights of some of the key features and terms</a></b>
|
||||
of <b>CC BY-SA 4.0</b>.<br>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="coda"><h3>Coda</h3>
|
||||
<p>
|
||||
<a href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fwww.ioccc.org%2F2024%2Fcable1%2Findex.html" rel="nofollow">Nu HTML check this web page</a><br>
|
||||
<a href="#top">Jump to top</a> <a href="#content">Jump to Content</a> <a href="#inventory">Jump to Inventory</a><br>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- END: this line ends content from: inc/footer.inventory.html -->
|
||||
<!-- START: this line starts content from: inc/bottom.default.html -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<!-- END: this line ends content from: inc/bottom.default.html -->
|
||||
@@ -0,0 +1,27 @@
|
||||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include<math.h>
|
||||
#include<string.h>
|
||||
#include<sys/mman.h>
|
||||
|
||||
#define a(_)typedef _##t
|
||||
#define _(_)_##printf
|
||||
#define x f(i,
|
||||
#define N f(k,
|
||||
#define u _Pragma("omp parallel for")f(h,
|
||||
#define f(u,n)for(I u=0;u<(n);u++)
|
||||
#define g(u,s)x s%11%5)N s/6&33)k[u[i]]=(t){(C*)A,A+s*D/4},A+=1088*s;
|
||||
|
||||
a(int8_)C;a(in)I;a(floa)F;a(struc){C*c;F*f;}t;enum{Z=32,W=64,E=2*W,D=Z*E,H=86*E,V='}\0'};C*P[V],X[H],Y[D],y[H];a(F
|
||||
_)[V];I*_=U" 炾ોİ䃃璱ᝓ၎瓓甧染ɐఛ瓁",U,s,p,f,R,z,$,B[D],open();F*A,*G[2],*T,w,b,c;a()Q[D];_t r,L,J,O[Z],l,a,K,v,k;Q
|
||||
m,e[4],d[3],n;I j(I e,F*o,I p,F*v,t*X){w=1e-5;x c=e^V?D:0)w+=r[i]*r[i]/D;x c)o[i]=r[i]/sqrt(w)*i[A+e*D];N $){x
|
||||
W)l[k]=w=fmax(fabs(o[i])/~-E,i?w:0);x W)y[i+k*W]=*o++/w;}u p)x $){I _=0,t=h*$+i;N W)_+=X->c[t*W+k]*y[i*W+k];v[h]=
|
||||
_*X->f[t]*l[i]+!!i*v[h];}x D-c)i[r]+=v[i];}I main(){A=mmap(0,8e9,1,2,f=open(M,f),0);x 2)~f?i[G]=malloc(3e9):exit(
|
||||
puts(M" not found"));x V)i[P]=(C*)A+4,A+=(I)*A;g(&m,V)g(&n,V)g(e,D)g(d,H)for(C*o;;s>=D?$=s=0:p<U||_()("%s",$[P]))if(!
|
||||
(*_?$=*++_:0)){if($<3&&p>=U)for(_()("\n\n> "),0<scanf("%[^\n]%*c",Y)?U=*B=1:exit(0),p=_(s)(o=X,"[INST] %s%s [/INST]",s?
|
||||
"":"<<SYS>>\n"S"\n<</SYS>>\n\n",Y);z=p-=z;U++[o+=z,B]=f)for(f=0;!f;z-=!f)for(f=V;--f&&f[P][z]|memcmp(f[P],o,z););p<U?
|
||||
$=B[p++]:fflush(0);x D)R=$*D+i,r[i]=m->c[R]*m->f[R/W];R=s++;N Z){f=k*D*D,$=W;x 3)j(k,L,D,i?G[~-i]+f+R*D:v,e[i]+k);N
|
||||
2)x D)b=sin(w=R/exp(i%E/14.)),c=1[w=cos(w),T=i+++(k?v:*G+f+R*D)],T[1]=b**T+c*w,*T=w**T-c*b;u Z){F*T=O[h],w=0;I A=h*E;x
|
||||
s){N E)i[k[L+A]=0,T]+=k[v+A]*k[i*D+*G+A+f]/11;w+=T[i]=exp(T[i]);}x s)N E)k[L+A]+=(T[i]/=k?1:w)*k[i*D+G[1]+A+f];}j(V,L
|
||||
,D,J,e[3]+k);x 2)j(k+Z,L,H,i?K:a,d[i]+k);x H)a[i]*=K[i]/(exp(-a[i])+1);j(V,a,D,L,d[$=H/$,2]+k);}w=j($=W,r,V,k,n);x
|
||||
V)w=k[i]>w?k[$=i]:w;}}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include<math.h>
|
||||
#include<string.h>
|
||||
#include<sys/mman.h>
|
||||
|
||||
#define a(_)typedef _##t
|
||||
#define _(_)_##printf
|
||||
#define x f(i,
|
||||
#define N f(k,
|
||||
#define u _Pragma("omp parallel for")f(h,
|
||||
#define f(u,n)for(I u=0;u<(n);u++)
|
||||
#define g(u,s)x s%11%5)N s/6&33)k[u[i]]=(t){(C*)A,A+s*D/4},A+=1088*s;
|
||||
|
||||
a(int8_)C;a(in)I;a(floa)F;a(struc){C*c;F*f;}t;enum{Z=32,W=64,E=2*W,D=Z*E,H=86*E,V='}\0'};C*P[V],X[H],Y[D],y[H];a(F
|
||||
_)[V];I*_=U" 炾ોİ䃃璱ᝓ၎瓓甧染ɐఛ瓁",U,s,p,f,R,z,$,B[D],open();F*A,*G[2],*T,w,b,c;a()Q[D];_t r,L,J,O[Z],l,a,K,v,k;Q
|
||||
m,e[4],d[3],n;I j(I e,F*o,I p,F*v,t*X){w=1e-5;x c=e^V?D:0)w+=r[i]*r[i]/D;x c)o[i]=r[i]/sqrt(w)*i[A+e*D];N $){x
|
||||
W)l[k]=w=fmax(fabs(o[i])/~-E,i?w:0);x W)y[i+k*W]=*o++/w;}u p)x $){I _=0,t=h*$+i;N W)_+=X->c[t*W+k]*y[i*W+k];v[h]=
|
||||
_*X->f[t]*l[i]+!!i*v[h];}x D-c)i[r]+=v[i];}I main(){A=mmap(0,8e9,1,2,f=open(M,f),0);x 2)~f?i[G]=malloc(3e9):exit(
|
||||
puts(M" not found"));x V)i[P]=(C*)A+4,A+=(I)*A;g(&m,V)g(&n,V)g(e,D)g(d,H)for(C*o;;s>=D?$=s=0:p<U||_()("%s",$[P]))if(!
|
||||
(*_?$=*++_:0)){if($<3&&p>=U)for(_()("\n\n> "),scanf("%[^\n]%*c",Y)?U=*B=1:exit(0),p=_(s)(o=X,"[INST] %s%s [/INST]",s?
|
||||
"":"<<SYS>>\n"S"\n<</SYS>>\n\n",Y);z=p-=z;U++[o+=z,B]=f)for(f=0;!f;z-=!f)for(f=V;--f&&f[P][z]|memcmp(f[P],o,z););p<U?
|
||||
$=B[p++]:fflush(0);x D)R=$*D+i,r[i]=m->c[R]*m->f[R/W];R=s++;N Z){f=k*D*D,$=W;x 3)j(k,L,D,i?G[~-i]+f+R*D:v,e[i]+k);N
|
||||
2)x D)b=sin(w=R/exp(i%E/14.)),c=1[w=cos(w),T=i+++(k?v:*G+f+R*D)],T[1]=b**T+c*w,*T=w**T-c*b;u Z){F*T=O[h],w=0;I A=h*E;x
|
||||
s){N E)i[k[L+A]=0,T]+=k[v+A]*k[i*D+*G+A+f]/11;w+=T[i]=exp(T[i]);}x s)N E)k[L+A]+=(T[i]/=k?1:w)*k[i*D+G[1]+A+f];}j(V,L
|
||||
,D,J,e[3]+k);x 2)j(k+Z,L,H,i?K:a,d[i]+k);x H)a[i]*=K[i]/(exp(-a[i])+1);j(V,a,D,L,d[$=H/$,2]+k);}w=j($=W,r,V,k,n);x
|
||||
V)w=k[i]>w?k[$=i]:w;}}
|
||||
Executable
+91
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# try.sh - demonstrate 2024/cable1
|
||||
|
||||
# make sure CC is set so that when we do make CC="$CC" it isn't empty. Doing it
|
||||
# this way allows us to have the user specify a different compiler in an easy way.
|
||||
#
|
||||
[[ -z "$CC" ]] && CC="cc"
|
||||
|
||||
# clear the screen
|
||||
#
|
||||
clear
|
||||
|
||||
# Verify we have the model
|
||||
#
|
||||
if [[ ! -s model ]]; then
|
||||
echo 'ERROR: model not found!' 1>&2
|
||||
echo 1>&2
|
||||
echo 'You must successfully run ./get_model.sh and download the model to run this program.' 1>&2
|
||||
echo 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# make sure the program has been built
|
||||
#
|
||||
read -r -n 1 -p "Press any key to when ready: "
|
||||
echo 1>&2
|
||||
make CC="$CC" all >/dev/null || exit 1
|
||||
|
||||
# select a game
|
||||
#
|
||||
export SELECT=""
|
||||
while [[ -z $SELECT ]]; do
|
||||
|
||||
export NAME=""
|
||||
export Z3=""
|
||||
export SAVE=""
|
||||
echo 1>&2
|
||||
echo 'Select a personality (if in doubt try 0):' 1>&2
|
||||
echo 1>&2
|
||||
echo ' 0 prog - Common ChatIOCCC' 1<&2
|
||||
echo ' 1 linux - As an imaginary Linux-based compiler' 1>&2
|
||||
echo ' 2 eeyore - The old grey donkey from the Winnie-the-Pooh books' 1>&2
|
||||
echo ' 3 rainman - In the style of Raymond, from the movie "Rain Man"' 1>&2
|
||||
echo ' 4 snoop - Attempts to answer in the style of Snoop Dogg' 1>&2
|
||||
echo 1>&2
|
||||
echo ' q Quit without running a personality' 1>&2
|
||||
echo 1>&2
|
||||
read -r -n 1 -p "Enter your selection: " SELECT
|
||||
echo 1>&2
|
||||
echo 1>&2
|
||||
|
||||
# validate prompt
|
||||
#
|
||||
case "$SELECT" in
|
||||
0) NAME="prog" ;;
|
||||
1) NAME="linux" ;;
|
||||
2) NAME="eeyore" ;;
|
||||
3) NAME="rainman" ;;
|
||||
4) NAME="snoop" ;;
|
||||
q) exit 0 ;;
|
||||
Q) exit 0 ;;
|
||||
*) echo 'ERROR: invalid selection, try again' 1>&2
|
||||
SELECT="" # ask for a different selection
|
||||
continue ;;
|
||||
esac
|
||||
export PROG="./$NAME"
|
||||
|
||||
# See if we can compile an openmp version
|
||||
#
|
||||
if [[ ! -x ${NAME}_openmp ]]; then
|
||||
make CC="$CC" "${NAME}_openmp" >/dev/null 2>&1 < /dev/null
|
||||
fi
|
||||
if [[ -x ${NAME}_openmp ]]; then
|
||||
# we have an openmp version, so use it
|
||||
#
|
||||
PROG="./${NAME}_openmp"
|
||||
fi
|
||||
done
|
||||
|
||||
# try the program
|
||||
#
|
||||
echo 'NOTE: Please be patient. This is not the fastest LLM agent.' 1>&2
|
||||
echo 1>&2
|
||||
echo 'NOTE: To exit, press CTRL+C' 1>&2
|
||||
echo 1>&2
|
||||
read -r -n 1 -p "Press any key to run: $PROG: "
|
||||
echo 1>&2
|
||||
echo 1>&2
|
||||
"$PROG"
|
||||
echo 1>&2
|
||||
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"no_comment" : "mandatory comment: because comments were removed from the original JSON spec",
|
||||
"entry_JSON_format_version" : "1.2 2024-09-25",
|
||||
"award" : "Prize in murky waters",
|
||||
"year" : 2024,
|
||||
"dir" : "cable2",
|
||||
"entry_id" : "2024_cable2",
|
||||
"title" : "salmon",
|
||||
"abstract" : "salmon recipe",
|
||||
"author_set" : [
|
||||
{
|
||||
"author_handle" : "Adrian_Cable"
|
||||
}
|
||||
],
|
||||
"manifest" : [
|
||||
{
|
||||
"file_path" : "prog.c",
|
||||
"inventory_order" : 20,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "c",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "entry source code"
|
||||
},
|
||||
{
|
||||
"file_path" : "Makefile",
|
||||
"inventory_order" : 30,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "makefile",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "entry Makefile"
|
||||
},
|
||||
{
|
||||
"file_path" : "prog.orig.c",
|
||||
"inventory_order" : 50,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "c",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "original source code"
|
||||
},
|
||||
{
|
||||
"file_path" : "try.sh",
|
||||
"inventory_order" : 100,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "shellscript",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "script to try entry"
|
||||
},
|
||||
{
|
||||
"file_path" : "2024_cable2.tar.bz2",
|
||||
"inventory_order" : 1415926535,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "tbz2",
|
||||
"display_via_github" : false,
|
||||
"entry_text" : "download entry tarball"
|
||||
},
|
||||
{
|
||||
"file_path" : ".entry.json",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "json",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "entry summary and manifest in JSON"
|
||||
},
|
||||
{
|
||||
"file_path" : ".gitignore",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "gitignore",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "list of files that should not be committed under git"
|
||||
},
|
||||
{
|
||||
"file_path" : ".path",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "path",
|
||||
"display_via_github" : false,
|
||||
"entry_text" : "directory path from top level directory"
|
||||
},
|
||||
{
|
||||
"file_path" : "README.md",
|
||||
"inventory_order" : 4000000000,
|
||||
"OK_to_edit" : true,
|
||||
"display_as" : "markdown",
|
||||
"display_via_github" : true,
|
||||
"entry_text" : "markdown source for this web page"
|
||||
},
|
||||
{
|
||||
"file_path" : "index.html",
|
||||
"inventory_order" : 4294967295,
|
||||
"OK_to_edit" : false,
|
||||
"display_as" : "html",
|
||||
"display_via_github" : false,
|
||||
"entry_text" : "this web page"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# sort with: ../../bin/sgi.sh
|
||||
*~
|
||||
*.dSYM
|
||||
*.o
|
||||
.DS_Store
|
||||
.*.swp
|
||||
@@ -0,0 +1 @@
|
||||
2024/cable2
|
||||
Binary file not shown.
@@ -0,0 +1,210 @@
|
||||
#!/usr/bin/env make
|
||||
#
|
||||
# 2024/cable2
|
||||
|
||||
#############################
|
||||
# shell used by this Makefile
|
||||
#############################
|
||||
|
||||
SHELL= bash
|
||||
|
||||
|
||||
#######################
|
||||
# common tool locations
|
||||
#######################
|
||||
|
||||
include ../../var.mk
|
||||
|
||||
|
||||
#####################
|
||||
# C compiler settings
|
||||
#####################
|
||||
|
||||
# Common C compiler warnings to silence
|
||||
#
|
||||
# Example: CSILENCE= -Wno-poison-system-directories
|
||||
#
|
||||
CSILENCE= -Wno-strict-prototypes
|
||||
|
||||
# Attempt to silence unknown warning options
|
||||
#
|
||||
CUNKNOWN= -Wno-unknown-warning-option
|
||||
|
||||
# Common C compiler warning flags
|
||||
#
|
||||
# NOTE: The addition of -pedantic to CWARN is a challenge that
|
||||
# You may wish to avoid if it proves too problematic.
|
||||
# There is NO penalty for removing -pedantic from CWARN.
|
||||
#
|
||||
CWARN= -Wall -Wextra -pedantic ${CSILENCE} ${CUNKNOWN}
|
||||
|
||||
# Compiler standard
|
||||
#
|
||||
CSTD= -std=gnu17
|
||||
|
||||
# Compiler bit architecture
|
||||
#
|
||||
# Example for 32-bitness: ARCH= -m32
|
||||
# Example for 64-bitness: ARCH= -m64
|
||||
#
|
||||
# NOTE: Normally one should NOT specify a specific architecture.
|
||||
#
|
||||
ARCH=
|
||||
|
||||
# Defines that are needed to compile
|
||||
#
|
||||
# Example: -Dfoo -Dbar=baz
|
||||
#
|
||||
CDEFINE=
|
||||
|
||||
# Include files that are needed to compile
|
||||
#
|
||||
# Example: CINCLUDE= -include stdio.h
|
||||
#
|
||||
CINCLUDE=
|
||||
|
||||
# Other flags to pass to the C compiler
|
||||
#
|
||||
# Example: COTHER= -fno-math-errno
|
||||
#
|
||||
COTHER=
|
||||
|
||||
# Optimization
|
||||
#
|
||||
# NOTE: Feel free to change the level of compiler optimization.
|
||||
# The "-O3" is just a friendly default you might wish to try.
|
||||
#
|
||||
# Example: OPT= -O0 -g
|
||||
#
|
||||
OPT= -O3
|
||||
|
||||
# Default flags for ANSI C compilation
|
||||
#
|
||||
CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${COTHER} ${OPT}
|
||||
|
||||
# Libraries needed to build
|
||||
#
|
||||
# Example: LDFLAGS= -lncurses -lm
|
||||
#
|
||||
LDFLAGS=
|
||||
|
||||
# C compiler to use
|
||||
#
|
||||
# NOTE: The IOCCC Judges recommend you leave CC as just "cc"
|
||||
# and NOT set it to clang, or gcc, or something else
|
||||
# unless you have a STRONG reason to do so.
|
||||
#
|
||||
# Setting CC to something other than "cc" makes your
|
||||
# code less portable to those who do not have your
|
||||
# particular C compiler. **hint**
|
||||
#
|
||||
# If you want to test your code with a particular C compiler,
|
||||
# use the make command line. For example:
|
||||
#
|
||||
# make all CC=clang
|
||||
# make all CC=gcc
|
||||
#
|
||||
CC= cc
|
||||
|
||||
# Compiler add-ons or replacements for clang only
|
||||
#
|
||||
ifeq "$(findstring $(CLANG),${CC})" "$(CLANG)"
|
||||
#
|
||||
# NOTE: This code is only invoked when CC is "clang"
|
||||
# such as when you use the make command line:
|
||||
#
|
||||
# make all CC=clang
|
||||
#
|
||||
CSILENCE+= -Wno-c99-compat -Wno-missing-variable-declarations \
|
||||
-Wno-poison-system-directories -Wno-sign-conversion -Wno-strict-prototypes
|
||||
#
|
||||
CWARN+= -Weverything
|
||||
#
|
||||
endif
|
||||
|
||||
# Specific add-ons or replacements for gcc only
|
||||
#
|
||||
ifeq "$(findstring $(GCC),${CC})" "$(GCC)"
|
||||
#
|
||||
# NOTE: This code is only invoked when CC is "gcc"
|
||||
# such as when you use the make command line:
|
||||
#
|
||||
# make all CC=gcc
|
||||
#
|
||||
CSILENCE+=
|
||||
#
|
||||
CWARN+=
|
||||
#
|
||||
endif
|
||||
|
||||
|
||||
###########################################
|
||||
# Special Makefile variables for this entry
|
||||
###########################################
|
||||
|
||||
ENTRY= prog
|
||||
PROG= ${ENTRY}
|
||||
#
|
||||
OBJ= ${PROG}.o
|
||||
TARGET= ${PROG}
|
||||
#
|
||||
ALT_OBJ=
|
||||
ALT_TARGET=
|
||||
|
||||
# list any data files supplied with your submission
|
||||
#
|
||||
# Example: DATA= curds whey
|
||||
#
|
||||
DATA=
|
||||
|
||||
|
||||
#################
|
||||
# build the entry
|
||||
#################
|
||||
|
||||
all: data ${TARGET}
|
||||
@${TRUE}
|
||||
|
||||
.PHONY: all alt data everything clean clobber
|
||||
|
||||
# how to compile
|
||||
#
|
||||
${PROG}: ${PROG}.c
|
||||
${CC} ${CFLAGS} ${PROG}.c -o $@ ${LDFLAGS}
|
||||
|
||||
# alternative executable
|
||||
#
|
||||
alt: data ${ALT_TARGET}
|
||||
@${TRUE}
|
||||
|
||||
${PROG}.alt: ${PROG}.alt.c
|
||||
${CC} ${CFLAGS} ${PROG}.alt.c -o $@ ${LDFLAGS}
|
||||
|
||||
# data files
|
||||
#
|
||||
data: ${DATA}
|
||||
@${TRUE}
|
||||
|
||||
# both all and alt
|
||||
#
|
||||
everything: all alt
|
||||
@${TRUE}
|
||||
|
||||
|
||||
###############
|
||||
# utility rules
|
||||
###############
|
||||
#
|
||||
clean:
|
||||
${RM} -f ${OBJ} ${ALT_OBJ}
|
||||
|
||||
clobber: clean
|
||||
${RM} -f ${TARGET} ${ALT_TARGET}
|
||||
${RM} -rf *.dSYM
|
||||
|
||||
|
||||
######################################
|
||||
# optional include of 1337 hacker rulz
|
||||
######################################
|
||||
|
||||
-include 1337.mk ../1337.mk ../../1337.mk
|
||||
Loaded 100 of 443 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user