diff --git a/18/18.2.go b/18/18.2.go new file mode 100644 index 0000000..5ef5f96 --- /dev/null +++ b/18/18.2.go @@ -0,0 +1,191 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +// cat input | go run 18.2.go + +type instruction struct { + instr string + register string + argIsInt bool + argInt int + argReg string +} + +var sends int + +func main() { + + scanner := bufio.NewScanner(os.Stdin) + registers0 := make(map[string]int) + registers1 := make(map[string]int) + var instructions = []instruction{} + var q0 = []int{} + var q1 = []int{} + + for scanner.Scan() { + s := strings.Split(scanner.Text(), " ") + i := instruction{s[0], s[1], false, -1, ""} + + if len(s) == 3 { + int, err := strconv.Atoi(s[2]) + if err != nil { + i.argIsInt = false + i.argReg = s[2] + } else { + i.argIsInt = true + i.argInt = int + } + } + + instructions = append(instructions, i) + } + + pc0 := 0 + pc1 := 0 + registers0["p"] = 0 + registers1["p"] = 1 + + for pc0 < len(instructions) && pc0 >= 0 && pc1 < len(instructions) && pc1 >= 0 { + pcpre0, pcpre1 := pc0, pc1 + pc0 = runInstr(0, ®isters0, instructions[pc0], pc0, &q0, &q1) + pc1 = runInstr(1, ®isters1, instructions[pc1], pc1, &q1, &q0) + if pc0 == pcpre0 && pc1 == pcpre1 { + fmt.Println("deadlock!", sends) + break + } + } + fmt.Println(sends) +} + +func runInstr(p int, registers *map[string]int, i instruction, pc int, qin *[]int, qout *[]int) int { + //fmt.Println(p, "PC:", pc, i, *registers, qin, qout) + register := i.register + + // Skip register if this is an int, because 'jgz 1 3' + _, err := strconv.Atoi(register) + if err != nil { + r := *registers + _, present := r[register] + if !present { + r[register] = 0 + } + } + + switch i.instr { + case "set": + pc = instrSet(registers, i, pc) + case "add": + pc = instrAdd(registers, i, pc) + case "mul": + pc = instrMul(registers, i, pc) + case "mod": + pc = instrMod(registers, i, pc) + case "snd": + pc = instrSnd(registers, i, pc, qout) + if p == 1 { + sends++ + } + case "rcv": + pc = instrRcv(registers, i, pc, qin) + case "jgz": + pc = instrJgz(registers, i, pc) + default: + fmt.Println("Instruction invalid!") + } + pc++ + //fmt.Println(p, "PC:", pc, i, *registers, qin, qout) + //fmt.Println() + return pc + +} + +func instrSet(registers *map[string]int, i instruction, pc int) int { + r := *registers + if i.argIsInt { + r[i.register] = i.argInt + } else { + r[i.register] = r[i.argReg] + } + return pc +} + +func instrAdd(registers *map[string]int, i instruction, pc int) int { + r := *registers + if i.argIsInt { + r[i.register] += i.argInt + } else { + r[i.register] += r[i.argReg] + } + return pc +} + +func instrMul(registers *map[string]int, i instruction, pc int) int { + r := *registers + if i.argIsInt { + r[i.register] *= i.argInt + } else { + r[i.register] *= r[i.argReg] + } + return pc +} + +func instrMod(registers *map[string]int, i instruction, pc int) int { + r := *registers + if i.argIsInt { + r[i.register] %= i.argInt + } else { + r[i.register] %= r[i.argReg] + } + return pc +} + +func instrSnd(registers *map[string]int, i instruction, pc int, snd *[]int) int { + r := *registers + n, err := strconv.Atoi(i.register) + if err == nil { + *snd = append(*snd, n) + } else { + *snd = append(*snd, r[i.register]) + } + return pc +} + +func instrRcv(registers *map[string]int, i instruction, pc int, snd *[]int) int { + r := *registers + s := *snd + if len(s) == 0 { + pc-- + } else { + x, t := s[0], s[1:] + r[i.register] = x + *snd = t + } + return pc +} + +func instrJgz(registers *map[string]int, i instruction, pc int) int { + r := *registers + + cmp := r[i.register] + n, err := strconv.Atoi(i.register) + if err == nil { + cmp = n + } + + if cmp > 0 { + if i.argIsInt { + pc = (pc + i.argInt) - 1 + } else { + pc = (pc + r[i.argReg]) - 1 + } + } + + return pc +} diff --git a/18/18.go b/18/18.go new file mode 100644 index 0000000..f272e92 --- /dev/null +++ b/18/18.go @@ -0,0 +1,154 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +// cat input | go run 18.go + +type instruction struct { + instr string + register string + argIsInt bool + argInt int + argReg string +} + +func main() { + + scanner := bufio.NewScanner(os.Stdin) + registers := make(map[string]int) + var instructions = []instruction{} + + for scanner.Scan() { + s := strings.Split(scanner.Text(), " ") + i := instruction{s[0], s[1], false, 0, ""} + + if len(s) == 3 { + int, err := strconv.Atoi(s[2]) + if err != nil { + i.argIsInt = false + i.argReg = s[2] + } else { + i.argIsInt = true + i.argInt = int + } + } + + instructions = append(instructions, i) + } + + pc := 0 + lastsnd := -1 + +loop: + for pc < len(instructions) && pc >= 0 { + fmt.Println("PC: ", pc, instructions[pc]) + fmt.Println(registers, lastsnd) + + instruction := instructions[pc].instr + register := instructions[pc].register + + _, present := registers[register] + if !present { + registers[register] = 0 + } + + switch instruction { + case "set": + pc = instrSet(®isters, instructions[pc], pc) + case "add": + pc = instrAdd(®isters, instructions[pc], pc) + case "mul": + pc = instrMul(®isters, instructions[pc], pc) + case "mod": + pc = instrMod(®isters, instructions[pc], pc) + case "snd": + pc = instrSnd(®isters, instructions[pc], pc, &lastsnd) + case "rcv": + pc = instrRcv(®isters, instructions[pc], pc, &lastsnd) + break loop + case "jgz": + pc = instrJgz(®isters, instructions[pc], pc) + default: + fmt.Println("Instruction invalid!") + } + fmt.Println(registers, lastsnd) + pc++ + + } + fmt.Println(registers, lastsnd) +} + +func instrSet(registers *map[string]int, i instruction, pc int) int { + r := *registers + if i.argIsInt { + r[i.register] = i.argInt + } else { + r[i.register] = r[i.argReg] + } + return pc +} + +func instrAdd(registers *map[string]int, i instruction, pc int) int { + r := *registers + if i.argIsInt { + r[i.register] += i.argInt + } else { + r[i.register] += r[i.argReg] + } + return pc +} + +func instrMul(registers *map[string]int, i instruction, pc int) int { + r := *registers + if i.argIsInt { + r[i.register] *= i.argInt + } else { + r[i.register] *= r[i.argReg] + } + return pc +} + +func instrMod(registers *map[string]int, i instruction, pc int) int { + r := *registers + if i.argIsInt { + r[i.register] %= i.argInt + } else { + r[i.register] %= r[i.argReg] + } + return pc +} + +func instrSnd(registers *map[string]int, i instruction, pc int, snd *int) int { + r := *registers + *snd = r[i.register] + fmt.Println("*snd:", *snd) + return pc +} + +func instrRcv(registers *map[string]int, i instruction, pc int, snd *int) int { + r := *registers + if i.argIsInt && i.argInt != 0 { + r[i.register] = *snd + } + return pc +} + +func instrJgz(registers *map[string]int, i instruction, pc int) int { + r := *registers + if i.argIsInt { + if r[i.register] > 0 { + pc = (pc + i.argInt) - 1 + } + } else { + if r[i.register] > 0 { + pc = (pc + r[i.argReg]) - 1 + } + } + return pc +}