Advertisement
Guest User

Untitled

a guest
Dec 9th, 2019
145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Julia 4.20 KB | None | 0 0
  1. module Intcode
  2.  
  3. using OffsetArrays
  4.  
  5. export parseInput, Program, runProgram, doOperation, onHalt, onStop
  6.  
  7. const parseInput(i) = split(i, ",") |>
  8.     lines -> map(x -> parse(Int, x), lines) |>
  9.     x -> OffsetArray(x, -1)
  10.  
  11. mutable struct Program
  12.     memory :: OffsetArrays.OffsetArray{Int64,1,Array{Int64,1}}
  13.     address :: Int
  14.     input :: Array{Int, 1}
  15.     output :: Array{Int, 1}
  16.     relativeBase :: Int
  17.     halted :: Bool
  18.     paused :: Bool
  19.     stopOnOutput :: Bool
  20.     onStop :: Function
  21.     onHalt :: Function
  22.     doOperation :: Function
  23. end
  24.  
  25. function parseOpcode(opcode::Int)
  26.     if opcode <= 10 || opcode == 99
  27.         return (opcode, (0, 0, 0))
  28.     end
  29.  
  30.     digs = digits(opcode; pad = 5)
  31.  
  32.     if [digs[1], digs[2]] == [9,9]
  33.         return (99, (digs[3], digs[4], digs[5]))
  34.     end
  35.  
  36.     return (digs[1], (digs[3], digs[4], digs[5]))
  37. end
  38.  
  39. function accessMemory(program::Program, address::Int, output=false)
  40.     diff = address-length(program.memory)+1
  41.  
  42.     if diff <= 0
  43.         return program.memory[address]
  44.     else
  45.         resize!(parent(program.memory), length(program.memory)+(diff))
  46.         return 0
  47.     end
  48. end
  49.  
  50. function applyMode(program::Program, mode::Int, value::Int, output=false)
  51.     if mode == 0
  52.         return !output ? accessMemory(program, value) : value
  53.     elseif mode == 1
  54.         return value
  55.     elseif mode == 2
  56.         return !output ? accessMemory(program, value+program.relativeBase) : value+program.relativeBase
  57.     end
  58. end
  59.  
  60. function parseInstructions(program::Program, opcode::Int, modes::Tuple{Int, Int, Int})
  61.     if opcode == 99
  62.         return (0, 0, 0)
  63.     elseif opcode == 3
  64.         return (0, 0, applyMode(program, modes[1], program.memory[program.address+1], true))
  65.     elseif opcode in [4, 9]
  66.         return (applyMode(program, modes[1], program.memory[program.address+1], false), 0, 0)
  67.     else
  68.         return map(((i, mode),) -> applyMode(program, mode, program.memory[program.address+i], i == 3), enumerate(modes))
  69.     end
  70. end
  71.  
  72. const operations  = Dict(
  73.     1 => (program, input, output) -> begin
  74.         program.memory[output] = input[1] + input[2]
  75.         program.address += 4
  76.     end,
  77.     2 => (program, input, output) -> begin
  78.         program.memory[output] = input[1] * input[2]
  79.         program.address += 4
  80.     end,
  81.     3 => (program, input, output) -> begin
  82.         program.memory[output] = popfirst!(program.input)
  83.         program.address += 2
  84.     end,
  85.     4 => (program, input, output) -> begin
  86.         push!(program.output, input[1])
  87.         program.address += 2
  88.        
  89.         if program.stopOnOutput
  90.             program.paused == true
  91.         end
  92.     end,
  93.     5 => (program, input, output) -> begin
  94.         program.address = input[1] != 0 ? input[2] : program.address + 3
  95.     end,
  96.     6 => (program, input, output) -> begin
  97.         program.address = input[1] == 0 ? input[2] : program.address + 3
  98.     end,
  99.     7 => (program, input, output) -> begin
  100.         program.memory[output] = input[1] < input[2] ? 1 : 0
  101.         program.address += 4
  102.     end,
  103.     8 => (program, input, output) -> begin
  104.         program.memory[output] = input[1] == input[2] ? 1 : 0
  105.         program.address += 4
  106.     end,
  107.     9 => (program, input, output) -> begin
  108.         program.relativeBase += input[1]
  109.         program.address += 2
  110.     end,
  111.     99 => (program, input, output) -> program.halted = true
  112. )
  113.  
  114. function doOperation(program::Program)
  115.     memoryValue = accessMemory(program, program.address)
  116.     opcode, modes = parseOpcode(memoryValue)
  117.  
  118.     instructions = parseInstructions(program, opcode, modes)
  119.     input = instructions[1:2]
  120.     outputAddress = instructions[end]
  121.  
  122.     accessMemory(program, outputAddress)
  123.  
  124.     #println("#", program.address, " " ,opcode, " ", modes, " ", memoryValue, " ", (instructions[1], instructions[2])  , " ", isnothing(outputAddress) ? 0 : outputAddress)
  125.  
  126.     operations[opcode](program, input, outputAddress)
  127. end
  128.  
  129. const runProgram(program::Program) = begin
  130.     while !program.halted
  131.         program.doOperation(program)
  132.     end
  133.  
  134.     program.onHalt(program)
  135. end
  136.  
  137. const onStop(program::Program) = println(program.output[end])
  138. const onHalt(program::Program) = println(program.output[end])
  139.  
  140. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement