part-02.scm 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. (import
  2. (except (rnrs base) let-values map error)
  3. (only (guile)
  4. lambda* λ
  5. current-output-port)
  6. (fileio)
  7. (math)
  8. (list-helpers)
  9. (array-helpers)
  10. ;; lists
  11. (srfi srfi-1)
  12. ;; let-values
  13. (srfi srfi-11)
  14. ;; hash tables
  15. (srfi srfi-69)
  16. ;; functional records
  17. (srfi srfi-9 gnu)
  18. (ice-9 pretty-print))
  19. (define lines (get-lines-from-file "input"))
  20. (define noop?
  21. (λ (line)
  22. (string=? line "noop")))
  23. (define addx?
  24. (λ (line)
  25. (string-prefix? "addx" line)))
  26. (define addx-get-number
  27. (λ (line)
  28. (string->number
  29. (second (string-split line #\space)))))
  30. (define signal-strength
  31. (λ (cycle register)
  32. (* cycle register)))
  33. (define-immutable-record-type <state>
  34. (make-state cycle register)
  35. state?
  36. (cycle state-cycle set-state-cycle)
  37. (register state-register set-state-register))
  38. (set-record-type-printer!
  39. <state>
  40. (lambda (record port)
  41. (simple-format port "<state: cycle:~a register:~a>"
  42. (state-cycle record)
  43. (state-register record))))
  44. (define initial-state (make-state 0 1))
  45. (define run-instruction
  46. (λ (state instruction)
  47. (cond
  48. [(noop? instruction)
  49. (set-state-cycle state (+ (state-cycle state) 1))]
  50. [(addx? instruction)
  51. (let ([register-increment (addx-get-number instruction)])
  52. (set-fields state
  53. ((state-cycle) (+ (state-cycle state) 1))
  54. ((state-register) (+ (state-register state) register-increment))))]
  55. [else
  56. (error "unrecognized instruction" instruction)])))
  57. ;; Idea: Translate addx <number> to 2 instructions, a noop
  58. ;; instruction and the actual adding instruction, both
  59. ;; taking 1 cycle. This should make it easier to write the
  60. ;; rest of the logic, because one does not have to consider
  61. ;; addx <number> taking 2 cycles.
  62. (define instructions
  63. (let iter-lines ([lines° lines])
  64. (cond
  65. [(null? lines°) '()]
  66. [else
  67. (let ([line (car lines°)])
  68. (cond
  69. [(noop? line)
  70. (cons line (iter-lines (cdr lines°)))]
  71. [(addx? line)
  72. (cons "noop"
  73. (cons line
  74. (iter-lines (cdr lines°))))]
  75. [else
  76. (error "unrecognized input line" line)]))])))
  77. (define display-crt-screen
  78. (λ (crt-screen)
  79. (let ([rows (array-len-in-dim crt-screen 0)]
  80. [cols (array-len-in-dim crt-screen 1)])
  81. (let iter-rows ([row-ind 0])
  82. (cond
  83. [(< row-ind rows)
  84. (let iter-cols ([col-ind 0])
  85. (cond
  86. [(< col-ind cols)
  87. (display (if (= (array-cell-ref crt-screen row-ind col-ind) 1) "#" ".")
  88. (current-output-port))
  89. (iter-cols (+ col-ind 1))]
  90. [else
  91. (display "\n" (current-output-port))
  92. (iter-rows (+ row-ind 1))]))]
  93. [else 'done])))))
  94. (define crt-pixel-lit?
  95. (λ (state)
  96. (let ([cycle-in-row (remainder (state-cycle state) 40)]
  97. [register (state-register state)])
  98. (and (>= cycle-in-row (- register 1))
  99. (<= cycle-in-row (+ register 1))))))
  100. ;; Now we can act, as if every instruction merely takes 1
  101. ;; cycle.
  102. (define crt-screen
  103. (let* ([rows 6]
  104. [cols 40]
  105. [screen (make-array 0 rows cols)])
  106. (let iter ([state initial-state]
  107. [instructions° instructions])
  108. (simple-format (current-output-port) "~a\n" state)
  109. (cond
  110. [(null? instructions°) screen]
  111. [else
  112. (let ([instruction (car instructions°)])
  113. (when (crt-pixel-lit? state)
  114. (let ([row-ind (inexact->exact (floor (/ (state-cycle state) cols)))]
  115. [col-ind (remainder (state-cycle state) cols)])
  116. (array-set! screen 1 row-ind col-ind)))
  117. (iter (run-instruction state instruction)
  118. (cdr instructions°)))]))))
  119. (display-crt-screen crt-screen)