Advent of Shell
I solved Advent of Code 2020, day 1, part 1 in pure AmigaShell. No ARexx! No cheating!
Forget head, tail, sed and other such Unix frivolities - or syntactic sugar like "for" and "while". Conditional branching with labels should be enough for everyone!
The tools used are mostly
sort, which always sorts in
ascending order, and
eval, which evaluates mathematical
expressions and bitwise logical operations.
For fetching values from the data, I opted for the line editor,
edit, which I use to extract a value from a row into
a temporary file which is then read into a variable. I also use
edit to treat the data file as a list, deleting
the first value after each completed loop.
It does take a while to run on my 14 MHz Amiga 1200. I didn't bother timing it, but probably at least a minute.
See a photo of it running (JPG, ~350K)
; Copy data file to RAM disk copy 1.dat t: ; Work in RAM disk cd t: ; Sort the data sort 1.dat 1.sort numeric ; The file 1.outer will be the "list" ; for the outer loop. copy 1.sort 1.outer ; Editor command for extracting ; the first value of a "list" file. echo "d 2 1000" > to_next ; Editor command for deleting the first line ; of a file, I.E. removing the first element ; in a "list". echo "d 1 1" > rem_1st ; Keep these commands in memory in order ; to minimize disk access. resident c:edit pure=force resident c:eval pure=force resident c:type pure=force resident c:list pure=force skip outer ; The outer loop lab outer ; Extract first value from list. edit 1.outer v.outer with to_next > nil: ; Check if we have a value. ; If not, skip to "fail", because then we're ; at the last item and haven't found any ; matching values. set outersize=`list 1.outer lformat="%L"` if $outersize eq "empty" skip fail endif ; Remove the first item from the list. edit 1.outer with rem_1st > nil: ; Store the value in a variable set outerval=`type v.outer` ; Prepare a fresh list for the inner loop. copy 1.sort 1.inner ; Skip to inner loop. skip inner ; The inner loop. lab inner ; Extract first value from list. edit 1.inner v.inner with to_next > nil: ; Check if we have a value. ; If not, skip back to the outer loop, because ; we're at the last item and haven't found any ; matching values. set innersize=`list v.inner lformat="%L"` if $innersize eq "empty" skip outer back endif ; Remove first item from list. edit 1.inner with rem_1st > nil: ; Store the value in a variable set innerval=`type v.inner` ; Add outer and inner value set res=`eval $innerval + $outerval` ; Skip back to the next outer value if ; we've exceeded the target value. if val $res gt 2020 skip outer back endif ; If we've hit the target value, calculate ; the final result and skip to the end ; (I.E. break the loop). if val $res eq 2020 set finalres=`eval $innerval * $outerval` skip end endif ; No match found, continue the inner loop skip inner back lab fail echo "No matches found in data." lab end echo "Final result: $finalres"
Download the code (text, ~1K)