You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
aoc-racket/2017/d14/main.rkt

64 lines
2.5 KiB
Racket

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

#lang reader "../aoc-lang.rkt"
(require racket/sequence sugar/list)
(provide (rename-out [#%mb #%module-begin]))
(define-macro (#%mb (STARS) (STR) ...)
#`(#%module-begin
(time ((if (eq? 'STARS ') one-star two-star) (format "~a" 'STR))) ...))
(define (knot-hashes str)
(for/list ([i (in-range 128)])
(knot-hash (format "~a-~a" str i))))
(define (one-star str)
(for*/sum ([kh (in-list (knot-hashes str))]
[int (in-list (kh->ints kh))])
int))
(define (two-star str)
(define vec (for*/vector ([kh (in-list (knot-hashes str))]
[int (in-list (kh->ints kh))])
(if (= int 1) 'used 'empty)))
(define (at-left-edge? idx) (= (modulo idx 128) 0))
(define (at-right-edge? idx) (= (modulo idx 128) 127))
(for/fold ([region 0])
([(val idx) (in-indexed vec)]
#:unless (number? val))
(let loop ([idx idx])
(cond
[(and (<= 0 idx (sub1 (vector-length vec))) (eq? (vector-ref vec idx) 'used))
(vector-set! vec idx region)
(unless (at-left-edge? idx) (loop (sub1 idx)))
(unless (at-right-edge? idx) (loop (add1 idx)))
(loop (+ idx 128))
(loop (- idx 128))
(add1 region)]
[else region]))))
(define (kh->ints kh)
(for*/list ([c (in-string kh)]
[num (in-value (string->number (string c) 16))]
[c (in-string (~r num #:base 2 #:min-width 4 #:pad-string "0"))])
(if (char=? c #\1) 1 0)))
(define (knot-hash seed-str [range-in 256])
(define ascii-chars (map char->integer (string->list seed-str)))
(define nums (reverse-segments range-in (append ascii-chars '(17 31 73 47 23)) #:reps 64))
(define dense-hash (for/list ([vals (in-slice 16 nums)])
(apply bitwise-xor vals)))
(string-append* (for/list ([num (in-list dense-hash)])
(~r num #:base 16 #:min-width 2 #:pad-string "0"))))
(define (reverse-segments range-in lens #:reps [reps 1])
(define vec (list->vector (range range-in)))
(for*/fold ([current-position 0]
[skip-size 0])
([rep (in-range reps)]
[len (in-list lens)])
(define posns (for/list ([i (in-range len)])
(modulo (+ current-position i) range-in)))
(for ([val (in-list (map (λ (posn) (vector-ref vec posn)) posns))]
[posn (in-list (reverse posns))])
(vector-set! vec posn val))
(values (+ current-position len skip-size) (add1 skip-size)))
(vector->list vec))