aoc-forth

Advent of code solutions in UF forth
git clone git://git.alexwennerberg.com/aoc-forth
Log | Files | Refs | README

commit 2d9273f4c47376b4ad83cf6b336587c1162e76ae
parent fb16f0f694ec44b9c4a127e0939cfb72fdaee6b9
Author: alex wennerberg <alex@alexwennerberg.com>
Date:   Sat, 26 Nov 2022 19:54:24 -0800

add new sols 2021

update readme

Diffstat:
D2021/01.f | 55-------------------------------------------------------
A2021/01a.f | 7+++++++
A2021/01b.f | 11+++++++++++
D2021/02.f | 57---------------------------------------------------------
A2021/02a.f | 16++++++++++++++++
A2021/02b.f | 18++++++++++++++++++
A2021/03a.f | 7+++++++
A2021/README.md | 11+++++++++++
A2021/dmath.f | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A2021/utils.f | 1+
MREADME.md | 22+++++++++-------------
11 files changed, 186 insertions(+), 125 deletions(-)

diff --git a/2021/01.f b/2021/01.f @@ -1,55 +0,0 @@ -h# 5000 constant filespace - -: initfile s" input01.txt" filename ; - -: readnum - 0 ( return val ) - begin - ( push char to stack [awkward] ) - filespace 1 fileread filespace c@ - swap over h# 0a <> and while ( not [newline or eof] ) - h# 30 - swap 10 * + ( convert ascii val ) - repeat - drop -; - - -: solvea - initfile - 0 - readnum - 2000 1 do - readnum dup -rot > 0<> 1+ rot - + swap - loop - drop -; - -: 3dup 2 pick 2 pick 2 pick ; - -variable total -variable last - -: solveb - initfile - readnum readnum readnum \ read 3 nums - 2000 3 do - 3dup + + dup \ sum - last @ - swap < 0<> negate total +! - last ! \ store variable - rot drop \ remove oldest value - readnum - loop - total @ -; - - -: boot - s" input01.txt" filename - solvea . cr - solveb . - bye -; -save 01.rom \ Replace with soln number -bye diff --git a/2021/01a.f b/2021/01a.f @@ -0,0 +1,7 @@ +variable last +: to-num ( a u -- n ) 0 -rot 0 do dup r@ + c@ h# 30 - rot 10 * + swap loop drop ; +: read-num ( -- n ) pad pad 10 accept to-num ; +: get-first-depth read-num last ! ; +: ?deeper dup last @ u> swap last ! ; +: count-deepers 1999 0 do read-num ?deeper if 1+ then loop ; +get-first-depth 0 count-deepers . cr bye diff --git a/2021/01b.f b/2021/01b.f @@ -0,0 +1,11 @@ +variable last +variable total +: to-num ( a u -- n ) 0 -rot 0 do dup r@ + c@ h# 30 - rot 10 * + swap loop drop ; +: read-num ( -- n ) pad pad 10 accept to-num ; +: 3dup 2 pick 2 pick 2 pick ; +: read-first-3 3 0 do read-num loop ; +: solve read-first-3 2000 3 do +3dup + + dup \ sum +last @ swap < 0<> negate total +! last ! +rot drop read-num loop total @ ; +solve . cr bye diff --git a/2021/02.f b/2021/02.f @@ -1,57 +0,0 @@ -h# 5000 constant filespace - -: chartonum h# 30 - ; - -: readline \ read a line to filespace - 0 begin dup - filespace + dup 1 fileread - swap c@ h# 0a <> and while ( not [newline or eof] ) - 1+ repeat drop -; - -variable xpos -variable ydepth -variable aim - -: getcommand - filespace c@ \ get direction - filespace 20 32 scan drop 1+ \ read until space - c@ chartonum swap \ get number -; -: solvea - 1000 0 do readline getcommand - dup 102 = if \ 'f' - over xpos +! - then dup 100 = if \ 'd' - over ydepth +! - then dup 117 = if \ 'u' - over negate ydepth +! - then - 2drop loop - xpos @ ydepth @ um* -; - -: solveb \ TODO figure out how to store double - s" input02.txt" filename - 1000 0 do readline getcommand - dup 102 = if \ 'f' - over xpos +! - over aim @ * ydepth +! - then dup 100 = if \ 'd' - over aim +! - then dup 117 = if \ 'u' - over negate aim +! - then - xpos @ ydepth @ aim @ . . . cr - 2drop loop - xpos @ ydepth @ .s um* -; - -: boot - s" input02.txt" filename - solvea d. cr \ TODO double math?? - 0 xpos ! 0 ydepth ! - solveb d. cr - bye ; -save 02.rom \ Replace with soln number -bye diff --git a/2021/02a.f b/2021/02a.f @@ -0,0 +1,16 @@ +\ doesnt need stdin, reads from file named "input.txt" +include dmath.f + +variable horiz 0 horiz ! +variable depth 0 depth ! + +: to-num ( a u -- n ) 0 -rot 0 do dup r@ + c@ h# 30 - rot 10 * + swap loop drop ; +: get-n bl parse to-num ; +: forward ( "N" -- ) get-n horiz +! ; +: down ( "N" -- ) get-n depth +! ; +: up ( "N" -- ) get-n negate depth +! ; +: solve horiz @ depth @ um* ; + +include input.txt + +solve d. cr bye diff --git a/2021/02b.f b/2021/02b.f @@ -0,0 +1,18 @@ +\ doesnt need stdin, reads from file named "input.txt" +\ copied mostly from peter to learn metaprogramming stuff +include dmath.f + +variable horiz 0 horiz ! +2variable depth 0 0 depth 2! +variable aim 0 aim ! + +: to-num ( a u -- n ) 0 -rot 0 do dup r@ + c@ h# 30 - rot 10 * + swap loop drop ; +: get-n bl parse to-num ; +: forward ( "N" -- ) get-n dup horiz +! aim @ * 0 depth 2@ d+ depth 2! ; +: down ( "N" -- ) get-n aim +! ; +: up ( "N" -- ) get-n negate aim +! ; +: solve depth 2@ horiz @ 1 m*/ ; + +include input.txt + +solve d. cr bye diff --git a/2021/03a.f b/2021/03a.f @@ -0,0 +1,7 @@ +variable 0 n 0 ! +variable bit 0 bit ! +: read-char pad pad 1 accept c@ ; +: rate create here 12 cells dup allot fill + does> ( -- a ) bit @ cell+ 1 bit +! +; +: solve 5 0 do r@ ; diff --git a/2021/README.md b/2021/README.md @@ -0,0 +1,11 @@ +Experimenting with aoc-2021. My plan is to do advent of code 2022 LIVE on twitch and upload the VODs to youtube. + +Many of these are "inspired" by peter fidelman's [solutions](https://gitlab.cs.washington.edu/fidelp/advent-of-code-2021) + +many of these won't run on the sample input + +Easiest way to run: + +``` +cat ##.f input.txt | uxncli [or uxnemu for solutions with visualizations] ufx.rom +``` diff --git a/2021/dmath.f b/2021/dmath.f @@ -0,0 +1,106 @@ +\ mostly taken from: +\ https://web.archive.org/web/20181118215700/http://excamera.com/files/j1demo/docforth/nuc.fs.html + +: d= ( a b c d -- f ) + >r \ a b c + rot xor \ b a^c + swap r> xor \ a^c b^d + or 0= ; +: d+ ( augend . addend . -- sum . ) + rot + >r ( augend addend) + over + ( augend sum) + dup rot ( sum sum augend) + u< if ( sum) + r> 1+ + else + r> + then ; ( sum . ) +: s>d dup 0< if -1 else 0 then ; +: dnegate + invert swap invert swap + 1 0 d+ ; +: dabs ( d -- ud ) dup 0< if dnegate then ; +: d- dnegate d+ ; +: d< \ ( al ah bl bh -- flag ) + rot \ al bl bh ah + 2dup = + if + 2drop u< + else + 2nip > + then ; +: d0= or 0= ; +: d0< 0 0 d< ; +: d2* 2dup d+ ; +: d2/ dup 31 lshift >r 2/ swap 2/ r> or swap ; +: dmax 2over 2over d< if 2swap then 2drop ; +: dmin 2over 2over d< 0= if 2swap then 2drop ; +: tf if -1 else 0 then ; + +variable scratch +: um* ( u1 u2 -- ud ) + scratch ! + 0 0 + 16 0 do + 2dup d+ + rot dup 0< if + 2* -rot + scratch @ 0 d+ + else + 2* -rot + then + loop + rot drop ; +: abssgn ( a b -- |a| |b| negf ) + 2dup xor 0< tf >r abs swap abs swap r> ; +: m* abssgn >r um* r> if dnegate then ; +: divstep + ( divisor dq hi ) + 2* + over 0< if 1+ then + swap 2* swap + rot ( dq hi divisor ) + 2dup >= if + tuck ( dq divisor hi divisor ) + - + swap ( dq hi divisor ) + rot 1+ ( hi divisor dq ) + rot ( divisor dq hi ) + else + -rot + then ; + +: um/mod ( ud u1 -- u2 u3 ) + -rot 16 0 do divstep loop + rot drop swap ; +: sm/rem ( d n -- r q ) ( symmetric ) + over >r >r dabs r@ abs um/mod + r> r@ xor 0< if negate then r> 0< if >r negate r> then ; +: */mod >r m* r> sm/rem ; +: */ */mod nip ; +: t2* over >r >r d2* r> 2* r> 0< tf 1 and + ; + +variable divisor +: m*/mod + divisor ! + tuck um* 2swap um* ( hi. lo. ) + ( m0 h l m1 ) + swap >r 0 d+ r> ( m h l ) + -rot ( l m h ) + 32 0 do + t2* + dup divisor @ >= if + divisor @ - + rot 1+ -rot + then + loop ; +: m*/ ( d1 n1 +n2 -- d2 ) m*/mod drop ; + +\ double printing +: (digit) ( u -- c ) 9 over < 7 and + [char] 0 + ; +: (d#) ( d1 -- d2 ) + 0 base @ um/mod >r base @ um/mod swap (digit) hold r> ; +: d#s ( d1 -- d2 ) begin (d#) 2dup or 0= until ; +: d#> ( d -- a u ) drop #> ; +: (d.) ( d -- a n ) 2dup dabs <# d#s 2swap nip sign d#> ; +: d. ( n -- ) (d.) type space ; diff --git a/2021/utils.f b/2021/utils.f @@ -0,0 +1 @@ +: is-num ( c -- f ) dup 48 >= swap 57 <= and ; diff --git a/README.md b/README.md @@ -1,27 +1,23 @@ # Forth AOC -Advent of Code solutions in [UF +**Watch me live on [twitch](https://twitch.tv/0000) each day at Midnight EST trying to do this challenge!** + +[Advent of Code](https://adventofcode.com/) solutions in [UF forth](http://www.call-with-current-continuation.org/uf/uf.html) Forth is a stack-based programming language. It is extremely small. UF is a Forth targeting the [uxn/varvara](https://100r.co/site/uxn.html) virtual computer. -I am going to try to work through 2021 using this language/environment as an exercise, and -in preparation for 2022. +2021 was me playing around. Doing 2022 live -A notable challenge will be that I only have access to 64kb of memory. May have to -use swap space of some sort. +A notable challenge will be that I only have access to 64kb of memory. -To run each solution (after building or acquiring ufx.rom from the `uf` repo): +To run each solution (after building or acquiring uxn and the ufx.rom from the `uf` repo): ``` -# make sure input is in inputN.txt (TODO: make a CLI arg) -uxncli ufx.rom < N.fs -uxnemu N.rom +cat ##[a/b].f input.txt | uxncli ufx.rom ``` -Working on different ways of importing things, some days require helper functions - -Some solutions have visualizations, others do not. For those that don't, you can use uxncli +Each day is split into two parts for simplicity. Code may be heavily duplicated. -part 1 and part 2 solutions will be printed to the console, newline separated +Use `uxnemu` for visual solutions (I'll call them out)