Advertisement
Guest User

Untitled

a guest
Dec 11th, 2019
274
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Julia 2.88 KB | None | 0 0
  1. module IntCode
  2.  
  3. export Computer
  4.  
  5. import Base: getindex, setindex!
  6.  
  7. struct Memory
  8.     data::Vector{Int}
  9. end
  10.  
  11. function getindex(m::Memory, i::Int)
  12.     i ≥ length(m.data) ? 0 : m.data[i + 1]
  13. end
  14.  
  15. function setindex!(m::Memory, v::Int, i::Int)
  16.     # expand memory by 50% of the requested value
  17.     if i ≥ length(m.data)
  18.         append!(m.data, zeros(round(Int, i * 1.5)))
  19.     end
  20.     setindex!(m.data, v, i + 1)
  21. end
  22.  
  23. mutable struct Computer
  24.     mem::Memory
  25.     ptr::Int
  26.     base::Int
  27.     halt::Bool
  28. end
  29.  
  30. Computer(program::Vector{Int}, ptr = 0, base = 0 , halt = false) =
  31.     Computer(Memory(copy(program)), ptr, base, halt)
  32.  
  33. Computer(s::AbstractString) = Computer(parse.(Int, split(s, ',')))
  34.  
  35. function (c::Computer)(input::AbstractVector{<:Int})
  36.     output = Int[]
  37.     mem = c.mem
  38.  
  39.     function arg(idx)
  40.         mode = mem[c.ptr] ÷ 10^(1 + idx) % 10
  41.         # position mode
  42.         if mode == 0
  43.             return mem[c.ptr + idx]
  44.         # immediate mode
  45.         elseif mode == 1
  46.             return c.ptr + idx
  47.         # relative mode
  48.         elseif mode == 2
  49.             return mem[c.ptr + idx] + c.base
  50.         else
  51.             error("Mode $mode is not supported.")
  52.         end
  53.     end
  54.  
  55.     while c.halt == false
  56.         opcode = mem[c.ptr] % 100
  57.  
  58.         # 1: addition
  59.         if opcode == 1
  60.             mem[arg(3)] = mem[arg(1)] + mem[arg(2)]
  61.             c.ptr += 4
  62.         # 2: multiplication
  63.         elseif opcode == 2
  64.             mem[arg(3)] = mem[arg(1)] * mem[arg(2)]
  65.             c.ptr += 4
  66.         # 3: input
  67.         elseif opcode == 3
  68.             if isempty(input)
  69.                 return output
  70.             else
  71.                 mem[arg(1)] = popfirst!(input)
  72.                 c.ptr += 2
  73.             end
  74.         # 4: output
  75.         elseif opcode == 4
  76.             push!(output, mem[arg(1)])
  77.             c.ptr += 2
  78.         # 5: jump-if-true
  79.         elseif opcode == 5
  80.             if mem[arg(1)] != 0
  81.                 c.ptr = mem[arg(2)]
  82.             else
  83.                 c.ptr += 3
  84.             end
  85.         # 6: jump-if-false
  86.         elseif opcode == 6
  87.             if mem[arg(1)] == 0
  88.                 c.ptr = mem[arg(2)]
  89.             else
  90.                 c.ptr += 3
  91.             end
  92.         # 7: less than
  93.         elseif opcode == 7
  94.             mem[arg(3)] = mem[arg(1)] < mem[arg(2)] ? 1 : 0
  95.             c.ptr += 4
  96.         # 8: equals
  97.         elseif opcode == 8
  98.             mem[arg(3)] = mem[arg(1)] == mem[arg(2)] ? 1 : 0
  99.             c.ptr += 4
  100.         # 9: adjust relative relative base
  101.         elseif opcode == 9
  102.             c.base += mem[arg(1)]
  103.             c.ptr += 2
  104.         # 99: halt
  105.         elseif opcode == 99
  106.             c.halt = true
  107.             return output
  108.         else
  109.             error("Program crashed: $opcode is not a valid opcode")
  110.         end
  111.     end
  112. end
  113.  
  114. (c::Computer)(input...) = c(collect(input))
  115.  
  116. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement