Alchemical Reduction
September 10, 2019
This task was solved in a blog entry by Philippe Gaultier, who explains that he started learning Scheme very recently. He gives this solution, using Chicken Scheme:
(import matchable clojurian.syntax chicken.file.posix chicken.io) (define (char-case-opposite-casing? a b) (let* ((a-code (char->integer a)) (b-code (char->integer b)) (diff (- a-code b-code))) (= (* 32 32) (* diff diff)))) (define (chem-react acc x) (match acc [() (cons x acc)] [(a . arest) (if (char-case-opposite-casing? a x) arest (cons x acc))])) (->> (open-input-file "/Users/pgaultier/Downloads/aoc5.txt") (read-line) (string->list) (foldl chem-react '()) (length) (print))
Perhaps Gaultier’s purpose was to learn about pattern matching or explore the Chicken ecosystem, but he took a simple task and made it complicated. Here is my solution:
(define (chem str) (let loop ((cs (string->list str)) (zs (list))) (cond ((null? cs) (reverse zs)) ((null? zs) (loop (cdr cs) (cons (car cs) zs))) ((and (char-ci=? (car cs) (car zs)) (not (char=? (car cs) (car zs)))) (loop (cdr cs) (cdr zs))) (else (loop (cdr cs) (cons (car cs) zs)))))) > (do ((str (read) (read))) ((eof-object? str)) (display (length (chem str))) (newline)) "AabcdZZqQ" 5 "aAbxXBctTCz" 1 #!eof
With respect to Gaultier, I prefer my solution, which is written in standard RnRS and requires no imports. The do
loop is a common idiom, and to my mind is easier to read than the “easy-to-read” ->>
macro; quickly, why is the null list passed to chem-react
in the call to foldl
? (It’s the initialization of acc
, which forces acc
to an unnatural position as the first parameter rather than the second parameter.) And despite Gaultier’s claim, character comparisons are better than integer-to-character conversions.
You can run the program at https://ideone.com/UY0PyP.
Nifty little exercise. Not sure if it qualifies as alchemy, but it’s definitely a nice challenge. Here is my take using Julia 1.1: https://pastebin.com/DE53t8nw
Cheers!
There was a bug in my previous attempt (a cool exercise in itself!) so here is the refined code: https://pastebin.com/5yddm5CJ
Cheers!
Here’s a simple solution in R7RS Scheme, focusing on clarity. The
imports are all trivial.
My Haskell solution relies mostly on a single
:
Regarding blog posts, I really like the elegance of this one, which shows this is just an exercise in group theory.
Here’s a little C++ solution, doing in-place modification of a 0-terminated char array.
A couple of solutions in Racket.
Here’s a solution in Python.
Output: