#!/usr/bin/env julia using Test mutable struct Instruction cycles :: UInt add :: Int end function parse_instruction_line(line) parts = split(line, limit=2) if parts[1] == "noop" return Instruction(1, 0) elseif parts[1] == "addx" return Instruction(2, parse(Int, parts[2])) else throw(DomainError("Unknown instruction: " * line)) end end function signal_strength_sum(io; end_cycle=220) X :: Int = 1 cycle :: Int = 1 signal_strength_sum :: Int = 0 next_test_cycle = 20 for line in eachline(io) if mod(cycle - 20, 40) == 0 && cycle <= end_cycle println(cycle, " ", X) signal_strength_sum += cycle * X next_test_cycle += 40 end inst = parse_instruction_line(line) new_cycle = cycle + inst.cycles if new_cycle > next_test_cycle signal_strength_sum += next_test_cycle * X next_test_cycle += 40 end cycle = new_cycle X += inst.add end println("last inst cycle ", cycle) signal_strength_sum += X * sum(filter(x -> x >= cycle, 20:40:end_cycle)) return signal_strength_sum end function get_crt(io; end_cycle=240) X :: Int = 2 # Note: add 1 to simplify 1-based indexing pending_instruction :: Union{Instruction, Nothing} = nothing screen = fill('.', (Int(ceil(end_cycle / 40)), 40)) nrows, ncols = size(screen) for i in 1:nrows for j in 1:ncols if abs(X - j) <= 1 screen[i, j] = "#"[1] else screen[i, j] = '.' end if pending_instruction === nothing if eof(io) continue end inst = parse_instruction_line(readline(io)) pending_instruction = inst end pending_instruction.cycles -= 1 if pending_instruction.cycles == 0 X += pending_instruction.add pending_instruction = nothing end end end return join(reduce(*, screen, dims=2, init=""), "\n") end function test() @testset "signal strength sum" verbose=true begin @test signal_strength_sum("example.txt") == 13140 @test signal_strength_sum("input.txt") == 13220 end @testset "crt test" verbose=true begin open("example.txt") do io @test get_crt(io) == chomp(read("example_crt.txt", String)) end open("input.txt") do io @test get_crt(io) == chomp(read("input_crt.txt", String)) end end end function main() if size(ARGS, 1) == 0 test() else infile = ARGS[1] println("infile = ", infile) println("signal strength sum = ", signal_strength_sum(infile)) open(infile, "r") do io println(get_crt(io)) end end end main()