Quest 4: Teeth of the Wind
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
Link to participate: https://everybody.codes/
You must log in or # to comment.
Uiua
Fortunately the ratios for the common gears all proved to be rational in part 3.
⌊×2025/÷⊏¯1_0[128 64 32 16 8] # ->32400 ⌈×⊙÷°⊟⊏¯1_0⊙10000000000000[128 64 32 16 8] # -> 625000000000 ⊜□⊸≠@\s "5 5|10 10|20 5" ⌊×100×⊃(÷∩⋕⊃⊣⊢|/×≡◇(/÷⊜⋕⊸≠@|)↘1↘¯1) # -> 400In 1980 we didn’t have tuple or set or vector types. We addressed elements of our cons-based data structures with nonsense incantations like
caddarand we liked it that way.(ql:quickload :cl-ppcre) (defun read-inputs (filename) (mapcar #'parse-integer (uiop:read-file-lines filename))) (defun main-1 (filename) (let ((gears (read-inputs filename))) (truncate (* 2025 (/ (first gears) (car (last gears))))))) (defun main-2 (filename) (let ((gears (read-inputs filename))) (ceiling (* 10000000000000 (/ (car (last gears)) (first gears)))))) (defun read-inputs-3 (filename) (flet ((parse-line (line) (or (ppcre:register-groups-bind (a b) ("^([0-9]+)[|]([0-9]+)$" line) (cons (parse-integer a) (parse-integer b))) (let ((a (parse-integer line))) (cons a a))))) (mapcar #'parse-line (uiop:read-file-lines filename)))) (defun gear-ratio-3 (gears) (labels ((iter (gears ratio) (if (< (length gears) 2) ratio (let ((out-gear (cdar gears)) (in-gear (caadr gears))) (iter (cdr gears) (* ratio (/ out-gear in-gear))))))) (iter gears 1))) (defun main-3 (filename) (let ((gears (read-inputs-3 filename))) (truncate (* 100 (gear-ratio-3 gears)))))maaath
Scheme/Guile
(import (rnrs io ports (6))) (define (parse-file file-name) (map string->number (string-split (call-with-input-file file-name get-string-all) #\newline))) (let* ((gears (parse-file "notes/everybody_codes_e2025_q04_p1.txt"))) (format #t "P1 Answer: ~a\n\n" (* 2025 (/ (car gears) (car (last-pair gears)))))) (let* ((gears (parse-file "notes/everybody_codes_e2025_q04_p2.txt"))) (format #t "P2 Answer: ~a\n\n" (ceiling (* 10000000000000 (/ (car (last-pair gears)) (car gears)))))) (define (parse-file-p3 file-name) (map (lambda (line) (map string->number(string-split line #\|))) (string-split (call-with-input-file file-name get-string-all) #\newline))) (let* ((gears (parse-file-p3 "notes/everybody_codes_e2025_q04_p3.txt"))) (format #t "P2 Answer: ~a\n\n" (floor (* 100 (apply * (map (lambda (gear) (if (= 1 (length gear)) 1 (/ (cadr gear) (car gear)))) gears)) (/ (caar gears) (caar (last-pair gears)))))))Rust
use num::{BigInt, Integer}; pub fn solve_part_1(input: &str) -> String { let gears: Vec<i64> = input.trim().lines().map(|g| g.parse().unwrap()).collect(); (2025 * gears[0] / gears.last().unwrap()).to_string() } pub fn solve_part_2(input: &str) -> String { let gears: Vec<i64> = input.trim().lines().map(|g| g.parse().unwrap()).collect(); let res = (BigInt::parse_bytes(b"10000000000000", 10).unwrap() * gears.last().unwrap()) .div_ceil(&(BigInt::ZERO + gears[0])); res.to_string() } pub fn solve_part_3(input: &str) -> String { let mut lines = input.trim().lines(); let first_gear = BigInt::parse_bytes(lines.next().unwrap().as_bytes(), 10).unwrap(); let mut nominator: BigInt = first_gear * 100; let mut denominator: BigInt = BigInt::ZERO + 1; for line in lines { let mut split = line.split("|"); denominator *= BigInt::parse_bytes(split.next().unwrap().as_bytes(), 10).unwrap(); match split.next() { Some(size) => { nominator *= BigInt::parse_bytes(size.as_bytes(), 10).unwrap(); } None => { break; } } } (nominator / denominator).to_string() }Nim
For part 3 I parse gears as tuples, with regular gears having same value on both ends e.g.
3|5 -> (3, 5) 3 -> (3, 3)proc parseGears(input: string): seq[int] = for line in input.splitLines(): result.add parseInt(line) proc parseNestedGears(input: string): seq[(int, int)] = for line in input.splitLines(): let nested = line.split('|').mapIt(it.parseInt) result.add: if nested.len == 1: (nested[0], nested[0]) else: (nested[0], nested[1]) proc solve_part1*(input: string): Solution = let gears = parseGears(input) result := 2025 * gears[0] div gears[^1] proc solve_part2*(input: string): Solution = let gears = parseGears(input) result := ceil(10000000000000'f64 / (gears[0] / gears[^1])).int proc solve_part3*(input: string): Solution = let gears = parseNestedGears(input) let ratios = (0..gears.high-1).mapIt(gears[it][1] / gears[it+1][0]) result := int(100 * ratios.prod)Full solution at Codeberg: solution.nim
I liked this one!
import Control.Arrow import Control.Monad import Data.List import Data.Ratio simpleTrain = uncurry (%) . (head &&& last) . map read compoundTrain input = let a = read $ head input z = read $ last input gs = map ( uncurry (%) . (read *** read . tail) . break (== '|') ) $ (tail . init) input in foldl' (/) (a % z) gs part1, part2, part3 :: [String] -> Integer part1 = floor . (2025 *) . simpleTrain part2 = ceiling . (10000000000000 /) . simpleTrain part3 = floor . (100 *) . compoundTrain main = forM_ [ ("everybody_codes_e2025_q04_p1.txt", part1), ("everybody_codes_e2025_q04_p2.txt", part2), ("everybody_codes_e2025_q04_p3.txt", part3) ] $ \(input, solve) -> readFile input >>= print . solve . lines





