Skip to content

Instantly share code, notes, and snippets.

@neuro-sys
Last active June 27, 2022 22:10
Show Gist options
  • Save neuro-sys/c65968b64c0ce0046216c7729c1b6e84 to your computer and use it in GitHub Desktop.
Save neuro-sys/c65968b64c0ce0046216c7729c1b6e84 to your computer and use it in GitHub Desktop.

s" lib.fs" included ...

This file is valid Forth source code, but also a Markdown file thanks to Forth allowing to define new syntax. Anything outside fenced code blocks will be skipped by the Forth compiler/interpreter. This allows code to be written in the literate programming style.

Day 1, Part 1

Full solution without the annotations.

s" lib.fs" included
s" 1.txt"  load-data data

: depth<   dup cell - @   over @  < ;
: collect  swap depth< if 1 else 0 then rot + ;
: solve    ['] collect data cell + 0 reduce ;

solve .

bye

Annotated code

We are given an ordered set of numbers, and asked to count the number of times when the two successive elements are ordered such that the next one is greater than the previous.

First, load the data into an array in memory with zero as a terminator.

s" 1.txt"  load-data data

load-data is defined in lib.fs, where I keep a collection of useful words that are not directly related to the problem, and generic enough to be used across most problems. Some of these words are reduce, for-each and load-data.

The next Markdown code block will also be skipped to prevent it from being compiled in.

load-data is defined is like this in lib.fs:

: load-data ( addr u "<spaces>ccc<space>" -- ) create included ;

It creates a dictionary entry for a name, and includes the data file into Forth compiler/interpreter.

Note that data files are formatted as valid Forth code to simplify the parsing process. They will typically compile in data blocks into dictionary.

Next, define depth< that will take the address of an element in the array, and compare it to the previous element. It keeps the address, and leaves an extra boolean flag in the stack indicating the result of the comparison.

: depth< ( addr -- addr f ) dup cell - @   over @  < ;

Next, define collect that will take an element address and the accumulator, and add 1 to the accumulator if depth< is true.

: collect ( addr acc -- addr acc ) swap depth< if 1 else 0 then rot + ;

Finally, define solve which will reduce the array from left to right starting from the second element.

It starts from the second element because depth< always compares with the previous element.

: solve    ['] collect data cell + 0 reduce ;

Print the solution and exit:

solve . bye
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment