Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. package intcode
  2. // VirtualMachine is an IntCode virtual machine.
  3. type VirtualMachine struct {
  4. ip int
  5. modes uint8
  6. opcodes [100]interface{}
  7. Memory []int
  8. Halted bool
  9. Input chan int
  10. Output chan int
  11. }
  12. // NewVirtualMachine creates a new IntCode virtual machine, initialised
  13. // to the given slice of memory.
  14. func NewVirtualMachine(memory []int, hasIO bool) *VirtualMachine {
  15. vm := &VirtualMachine{
  16. ip: 0,
  17. Memory: memory,
  18. Halted: false,
  19. opcodes: [100]interface{}{
  20. 1: AddOpcode,
  21. 2: MulOpcode,
  22. 3: ReadOpCode,
  23. 4: WriteOpCode,
  24. 5: JumpIfTrueOpCode,
  25. 6: JumpIfFalseOpCode,
  26. 7: LessThanOpCode,
  27. 8: EqualsOpCode,
  28. 99: HaltOpcode,
  29. },
  30. }
  31. if hasIO {
  32. vm.Input = make(chan int, 1)
  33. vm.Output = make(chan int, 1)
  34. }
  35. return vm
  36. }
  37. func (vm *VirtualMachine) arg(pos int) int {
  38. mask := uint8(1) << uint8(pos)
  39. if vm.modes&mask == mask {
  40. return vm.Memory[vm.ip+1+pos]
  41. } else {
  42. return vm.Memory[vm.Memory[vm.ip+1+pos]]
  43. }
  44. }
  45. // Run repeatedly executes instructions until the VM halts.
  46. func (vm *VirtualMachine) Run() {
  47. for !vm.Halted {
  48. instruction := vm.Memory[vm.ip]
  49. opcode := instruction % 100
  50. vm.modes = 0
  51. mask := uint8(1)
  52. for i := instruction / 100; i > 0; i /= 10 {
  53. if i%10 == 1 {
  54. vm.modes = vm.modes | mask
  55. }
  56. mask = mask << 1
  57. }
  58. vm.opcodes[opcode].(OpcodeFunc)(vm)
  59. }
  60. if vm.Output != nil {
  61. close(vm.Output)
  62. }
  63. }
  64. // Reset resets the memory to the given slice, and all other state back to its original value.
  65. func (vm *VirtualMachine) Reset(memory []int) {
  66. copy(vm.Memory, memory)
  67. vm.ip = 0
  68. vm.Halted = false
  69. if vm.Input != nil {
  70. vm.Input = make(chan int, 1)
  71. vm.Output = make(chan int, 1)
  72. }
  73. }