Bläddra i källkod

Minor day 7 optimisations

Each VM doesn't need its own opcode array (hopefully); use a
pre-allocated memory bank for the memory of all amplifiers.
master
Chris Smith 4 år sedan
förälder
incheckning
cea1ff0bc9
Signerad av: Chris Smith <chris@chameth.com> GPG-nyckel ID: 3A2D4BBDC4A3C9A9
3 ändrade filer med 48 tillägg och 51 borttagningar
  1. 9
    12
      07/main.go
  2. 32
    20
      intcode/ops.go
  3. 7
    19
      intcode/vm.go

+ 9
- 12
07/main.go Visa fil

6
 	"github.com/csmith/aoc-2019/intcode"
6
 	"github.com/csmith/aoc-2019/intcode"
7
 )
7
 )
8
 
8
 
9
-func copyOf(memory []int) []int {
10
-	res := make([]int, len(memory))
11
-	copy(res, memory)
12
-	return res
13
-}
14
-
15
-func runPipeline(program []int, ps []int, feedback bool) int {
9
+func runPipeline(memoryBanks []int, program []int, ps []int, feedback bool) int {
16
 	// Create a series of VMs for our amplifiers
10
 	// Create a series of VMs for our amplifiers
17
 	vms := make([]*intcode.VirtualMachine, len(ps))
11
 	vms := make([]*intcode.VirtualMachine, len(ps))
18
 	for i := 0; i < len(ps); i++ {
12
 	for i := 0; i < len(ps); i++ {
19
-		vms[i] = intcode.NewVirtualMachine(copyOf(program), true)
13
+		memory := memoryBanks[i*len(program) : (i+1)*len(program)]
14
+		copy(memory, program)
15
+		vms[i] = intcode.NewVirtualMachine(memory, true)
20
 	}
16
 	}
21
 
17
 
22
 	// Link all the inputs and outputs
18
 	// Link all the inputs and outputs
46
 	return <-vms[len(vms)-1].Output
42
 	return <-vms[len(vms)-1].Output
47
 }
43
 }
48
 
44
 
49
-func maxOutput(input []int, ps []int, feedback bool) int {
45
+func maxOutput(memoryBanks []int, input []int, ps []int, feedback bool) int {
50
 	max := 0
46
 	max := 0
51
 	for _, p := range common.Permutations(ps) {
47
 	for _, p := range common.Permutations(ps) {
52
-		val := runPipeline(input, p, feedback)
48
+		val := runPipeline(memoryBanks, input, p, feedback)
53
 		if val > max {
49
 		if val > max {
54
 			max = val
50
 			max = val
55
 		}
51
 		}
59
 
55
 
60
 func main() {
56
 func main() {
61
 	input := common.ReadCsvAsInts("07/input.txt")
57
 	input := common.ReadCsvAsInts("07/input.txt")
62
-	fmt.Println(maxOutput(input, []int{0, 1, 2, 3, 4}, false))
63
-	fmt.Println(maxOutput(input, []int{5, 6, 7, 8, 9}, true))
58
+	memoryBanks := make([]int, len(input)*5)
59
+	fmt.Println(maxOutput(memoryBanks, input, []int{0, 1, 2, 3, 4}, false))
60
+	fmt.Println(maxOutput(memoryBanks, input, []int{5, 6, 7, 8, 9}, true))
64
 }
61
 }

+ 32
- 20
intcode/ops.go Visa fil

1
 package intcode
1
 package intcode
2
 
2
 
3
-// OpcodeFunc is a function that describes an opcode implemented in the VM.
4
-type OpcodeFunc = func(vm *VirtualMachine)
3
+// opcodeFunc is a function that describes an opcode implemented in the VM.
4
+type opcodeFunc = func(vm *VirtualMachine)
5
 
5
 
6
-// AddOpcode takes the values specified by args 1 and 2, adds them together, and stores at the memory address given
6
+var opcodes = [100]opcodeFunc{
7
+	1:  addOpcode,
8
+	2:  mulOpcode,
9
+	3:  readOpCode,
10
+	4:  writeOpCode,
11
+	5:  jumpIfTrueOpCode,
12
+	6:  jumpIfFalseOpCode,
13
+	7:  lessThanOpCode,
14
+	8:  equalsOpCode,
15
+	99: haltOpcode,
16
+}
17
+
18
+// addOpcode takes the values specified by args 1 and 2, adds them together, and stores at the memory address given
7
 // by arg 3.
19
 // by arg 3.
8
-func AddOpcode(vm *VirtualMachine) {
20
+func addOpcode(vm *VirtualMachine) {
9
 	vm.Memory[vm.Memory[vm.ip+3]] = vm.arg(0) + vm.arg(1)
21
 	vm.Memory[vm.Memory[vm.ip+3]] = vm.arg(0) + vm.arg(1)
10
 	vm.ip += 4
22
 	vm.ip += 4
11
 }
23
 }
12
 
24
 
13
-// MulOpcode takes the values specified by args 1 and 2, multiplies them together, and stores at the memory address
25
+// mulOpcode takes the values specified by args 1 and 2, multiplies them together, and stores at the memory address
14
 // given by arg 3.
26
 // given by arg 3.
15
-func MulOpcode(vm *VirtualMachine) {
27
+func mulOpcode(vm *VirtualMachine) {
16
 	vm.Memory[vm.Memory[vm.ip+3]] = vm.arg(0) * vm.arg(1)
28
 	vm.Memory[vm.Memory[vm.ip+3]] = vm.arg(0) * vm.arg(1)
17
 	vm.ip += 4
29
 	vm.ip += 4
18
 }
30
 }
19
 
31
 
20
-// ReadOpCode reads a value from the input stream and stores it at the memory address given by arg 1.
21
-func ReadOpCode(vm *VirtualMachine) {
32
+// readOpCode reads a value from the input stream and stores it at the memory address given by arg 1.
33
+func readOpCode(vm *VirtualMachine) {
22
 	vm.Memory[vm.Memory[vm.ip+1]] = <-vm.Input
34
 	vm.Memory[vm.Memory[vm.ip+1]] = <-vm.Input
23
 	vm.ip += 2
35
 	vm.ip += 2
24
 }
36
 }
25
 
37
 
26
-// WriteOpCode writes the value specified by the first argument to the output stream.
27
-func WriteOpCode(vm *VirtualMachine) {
38
+// writeOpCode writes the value specified by the first argument to the output stream.
39
+func writeOpCode(vm *VirtualMachine) {
28
 	vm.Output <- vm.arg(0)
40
 	vm.Output <- vm.arg(0)
29
 	vm.ip += 2
41
 	vm.ip += 2
30
 }
42
 }
31
 
43
 
32
-// JumpIfTrueOpCode checks if the first argument is not zero, and if so jumps to the second argument.
33
-func JumpIfTrueOpCode(vm *VirtualMachine) {
44
+// jumpIfTrueOpCode checks if the first argument is not zero, and if so jumps to the second argument.
45
+func jumpIfTrueOpCode(vm *VirtualMachine) {
34
 	if vm.arg(0) != 0 {
46
 	if vm.arg(0) != 0 {
35
 		vm.ip = vm.arg(1)
47
 		vm.ip = vm.arg(1)
36
 	} else {
48
 	} else {
38
 	}
50
 	}
39
 }
51
 }
40
 
52
 
41
-// JumpIfFalseOpCode checks if the first argument is zero, and if so jumps to the second argument.
42
-func JumpIfFalseOpCode(vm *VirtualMachine) {
53
+// jumpIfFalseOpCode checks if the first argument is zero, and if so jumps to the second argument.
54
+func jumpIfFalseOpCode(vm *VirtualMachine) {
43
 	if vm.arg(0) == 0 {
55
 	if vm.arg(0) == 0 {
44
 		vm.ip = vm.arg(1)
56
 		vm.ip = vm.arg(1)
45
 	} else {
57
 	} else {
47
 	}
59
 	}
48
 }
60
 }
49
 
61
 
50
-// LessThanOpCode checks if the first argument is less than the second, and stores the result at the address given
62
+// lessThanOpCode checks if the first argument is less than the second, and stores the result at the address given
51
 // by the third argument.
63
 // by the third argument.
52
-func LessThanOpCode(vm *VirtualMachine) {
64
+func lessThanOpCode(vm *VirtualMachine) {
53
 	if vm.arg(0) < vm.arg(1) {
65
 	if vm.arg(0) < vm.arg(1) {
54
 		vm.Memory[vm.Memory[vm.ip+3]] = 1
66
 		vm.Memory[vm.Memory[vm.ip+3]] = 1
55
 	} else {
67
 	} else {
58
 	vm.ip += 4
70
 	vm.ip += 4
59
 }
71
 }
60
 
72
 
61
-// EqualsOpCode checks if the first argument is equal to the second, and stores the result at the address given
73
+// equalsOpCode checks if the first argument is equal to the second, and stores the result at the address given
62
 // by the third argument.
74
 // by the third argument.
63
-func EqualsOpCode(vm *VirtualMachine) {
75
+func equalsOpCode(vm *VirtualMachine) {
64
 	if vm.arg(0) == vm.arg(1) {
76
 	if vm.arg(0) == vm.arg(1) {
65
 		vm.Memory[vm.Memory[vm.ip+3]] = 1
77
 		vm.Memory[vm.Memory[vm.ip+3]] = 1
66
 	} else {
78
 	} else {
69
 	vm.ip += 4
81
 	vm.ip += 4
70
 }
82
 }
71
 
83
 
72
-// HaltOpcode halts the VM and takes no arguments.
73
-func HaltOpcode(vm *VirtualMachine) {
84
+// haltOpcode halts the VM and takes no arguments.
85
+func haltOpcode(vm *VirtualMachine) {
74
 	vm.Halted = true
86
 	vm.Halted = true
75
 }
87
 }

+ 7
- 19
intcode/vm.go Visa fil

2
 
2
 
3
 // VirtualMachine is an IntCode virtual machine.
3
 // VirtualMachine is an IntCode virtual machine.
4
 type VirtualMachine struct {
4
 type VirtualMachine struct {
5
-	ip      int
6
-	modes   uint8
7
-	opcodes [100]interface{}
8
-	Memory  []int
9
-	Halted  bool
10
-	Input   chan int
11
-	Output  chan int
5
+	ip     int
6
+	modes  uint8
7
+	Memory []int
8
+	Halted bool
9
+	Input  chan int
10
+	Output chan int
12
 }
11
 }
13
 
12
 
14
 // NewVirtualMachine creates a new IntCode virtual machine, initialised
13
 // NewVirtualMachine creates a new IntCode virtual machine, initialised
18
 		ip:     0,
17
 		ip:     0,
19
 		Memory: memory,
18
 		Memory: memory,
20
 		Halted: false,
19
 		Halted: false,
21
-		opcodes: [100]interface{}{
22
-			1:  AddOpcode,
23
-			2:  MulOpcode,
24
-			3:  ReadOpCode,
25
-			4:  WriteOpCode,
26
-			5:  JumpIfTrueOpCode,
27
-			6:  JumpIfFalseOpCode,
28
-			7:  LessThanOpCode,
29
-			8:  EqualsOpCode,
30
-			99: HaltOpcode,
31
-		},
32
 	}
20
 	}
33
 
21
 
34
 	if hasIO {
22
 	if hasIO {
63
 			mask = mask << 1
51
 			mask = mask << 1
64
 		}
52
 		}
65
 
53
 
66
-		vm.opcodes[opcode].(OpcodeFunc)(vm)
54
+		opcodes[opcode](vm)
67
 	}
55
 	}
68
 	if vm.Output != nil {
56
 	if vm.Output != nil {
69
 		close(vm.Output)
57
 		close(vm.Output)

Laddar…
Avbryt
Spara