Add day 14 and 15
This commit is contained in:
parent
2fc461d579
commit
83f76cadcb
|
@ -0,0 +1,242 @@
|
||||||
|
from pprint import pprint
|
||||||
|
from collections import deque
|
||||||
|
import fileinput
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
class Elf:
|
||||||
|
power = 3
|
||||||
|
locations = set()
|
||||||
|
deaths = 0
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.health = 200
|
||||||
|
self.targeted = False
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "E"
|
||||||
|
|
||||||
|
|
||||||
|
class Goblin:
|
||||||
|
enemy = Elf
|
||||||
|
power = 3
|
||||||
|
locations = set()
|
||||||
|
deaths = 0
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.health = 200
|
||||||
|
self.targeted = False
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "G"
|
||||||
|
|
||||||
|
|
||||||
|
Elf.enemy = Goblin
|
||||||
|
|
||||||
|
|
||||||
|
class Wall:
|
||||||
|
enemy = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.targeted = False
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "#"
|
||||||
|
|
||||||
|
|
||||||
|
class Empty:
|
||||||
|
enemy = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.targeted = False
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "." if not self.targeted else "\033[33m?\033[0m"
|
||||||
|
|
||||||
|
|
||||||
|
NEIGHBORS = [(0, -1), (-1, 0), (1, 0), (0, 1)]
|
||||||
|
|
||||||
|
|
||||||
|
def read():
|
||||||
|
field = []
|
||||||
|
Elf.deaths = 0
|
||||||
|
Goblin.deaths = 0
|
||||||
|
Elf.locations.clear()
|
||||||
|
Goblin.locations.clear()
|
||||||
|
for y, line in enumerate(fileinput.input()):
|
||||||
|
row = []
|
||||||
|
|
||||||
|
for x, char in enumerate(line.rstrip()):
|
||||||
|
if char == "E":
|
||||||
|
row.append(Elf())
|
||||||
|
Elf.locations.add((x, y))
|
||||||
|
elif char == "G":
|
||||||
|
row.append(Goblin())
|
||||||
|
Goblin.locations.add((x, y))
|
||||||
|
elif char == "#":
|
||||||
|
row.append(Wall())
|
||||||
|
elif char == ".":
|
||||||
|
row.append(Empty())
|
||||||
|
else:
|
||||||
|
raise ValueError(char)
|
||||||
|
|
||||||
|
field.append(row)
|
||||||
|
|
||||||
|
return field
|
||||||
|
|
||||||
|
|
||||||
|
def distance(a, b):
|
||||||
|
(ax, ay), (bx, by) = a, b
|
||||||
|
return abs(ax - bx) + abs(ay - by)
|
||||||
|
|
||||||
|
|
||||||
|
def find_closest(field, pos, targets):
|
||||||
|
width = len(field[0])
|
||||||
|
height = len(field)
|
||||||
|
|
||||||
|
queue = deque([[pos]])
|
||||||
|
seen = {pos}
|
||||||
|
paths = []
|
||||||
|
|
||||||
|
while queue:
|
||||||
|
path = queue.popleft()
|
||||||
|
x, y = path[-1]
|
||||||
|
|
||||||
|
if (x, y) in targets:
|
||||||
|
paths.append(path[1:])
|
||||||
|
|
||||||
|
for dx, dy in NEIGHBORS:
|
||||||
|
x_, y_ = x + dx, y + dy
|
||||||
|
if 0 <= x_ < width and 0 <= y_ < height \
|
||||||
|
and type(field[y_][x_]) is Empty \
|
||||||
|
and (x_, y_) not in seen:
|
||||||
|
queue.append(path + [(x_, y_)])
|
||||||
|
seen.add((x_, y_))
|
||||||
|
|
||||||
|
if not paths or [] in paths:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return min(paths, key=lambda path: (len(path), path[-1][1], path[-1][0], path[0][1], path[0][0]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def move(field, x, y, value):
|
||||||
|
for row in field:
|
||||||
|
for col in row:
|
||||||
|
col.targeted = False
|
||||||
|
|
||||||
|
targets = []
|
||||||
|
for tx, ty in value.enemy.locations:
|
||||||
|
targets.extend([(tx + dx, ty + dy) for dx, dy in NEIGHBORS])
|
||||||
|
|
||||||
|
if not targets:
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
for tx, ty in targets:
|
||||||
|
field[ty][tx].targeted = True
|
||||||
|
|
||||||
|
closest = find_closest(field, (x, y), targets)
|
||||||
|
# print_field(field, highlight=(x, y), path=closest)
|
||||||
|
# time.sleep(0.3)
|
||||||
|
|
||||||
|
if closest:
|
||||||
|
tx, ty = closest[0]
|
||||||
|
if type(field[ty][tx]) is Empty:
|
||||||
|
# print(f"{field[y][x]}@{x},{y} moves to {tx},{ty}")
|
||||||
|
type(value).locations.discard((x, y))
|
||||||
|
type(value).locations.add((tx, ty))
|
||||||
|
field[ty][tx] = field[y][x]
|
||||||
|
field[y][x] = Empty()
|
||||||
|
return tx, ty
|
||||||
|
return x, y
|
||||||
|
|
||||||
|
|
||||||
|
def attack(field, x, y, value):
|
||||||
|
width = len(field[0])
|
||||||
|
height = len(field)
|
||||||
|
|
||||||
|
neighbors = [(field[y + y_][x + x_], (x + x_, y + y_))
|
||||||
|
for x_, y_ in NEIGHBORS
|
||||||
|
if 0 <= y + y_ < width and 0 <= x + x_ < width and \
|
||||||
|
type(field[y + y_][x + x_]) is value.enemy]
|
||||||
|
if not neighbors:
|
||||||
|
return
|
||||||
|
|
||||||
|
target, (tx, ty) = \
|
||||||
|
min(neighbors, key=lambda x: (x[0].health, x[1][1], x[1][0]))
|
||||||
|
# print(f"{value}@{x},{y}:{value.health} attacks "
|
||||||
|
# f"{target}@{tx},{ty}:{target.health}->{target.health - value.power}")
|
||||||
|
target.health -= value.power
|
||||||
|
|
||||||
|
if target.health <= 0:
|
||||||
|
# print(f"{target}@{tx,ty} dies :(")
|
||||||
|
type(target).locations.discard((tx, ty))
|
||||||
|
type(target).deaths += 1
|
||||||
|
field[ty][tx] = Empty()
|
||||||
|
|
||||||
|
|
||||||
|
def print_field(field, steps=None, highlight=None, path=None):
|
||||||
|
if steps is not None:
|
||||||
|
print(f"round={steps}")
|
||||||
|
for y, row in enumerate(field):
|
||||||
|
units = []
|
||||||
|
for x, value in enumerate(row):
|
||||||
|
if highlight == (x, y):
|
||||||
|
print(end="\033[31;1m")
|
||||||
|
if path and (x, y) in path:
|
||||||
|
print(end="\033[44;1m")
|
||||||
|
|
||||||
|
print(value, end="\033[0m")
|
||||||
|
|
||||||
|
if type(value) in (Goblin, Elf):
|
||||||
|
units.append(value)
|
||||||
|
|
||||||
|
etc = sorted(units, key=lambda unit: (str(unit), unit.health))
|
||||||
|
print(" ", ", ".join(f"{x}({x.health})" for x in etc))
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
def step(field, steps):
|
||||||
|
# print_field(field, steps)
|
||||||
|
seen_units = set()
|
||||||
|
for y, row in enumerate(field):
|
||||||
|
for x, value in enumerate(row):
|
||||||
|
if type(value) not in (Elf, Goblin) or value in seen_units:
|
||||||
|
continue
|
||||||
|
seen_units.add(value)
|
||||||
|
|
||||||
|
tx, ty = move(field, x, y, value)
|
||||||
|
attack(field, tx, ty, value)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
field = read()
|
||||||
|
|
||||||
|
steps = 0
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
step(field, steps)
|
||||||
|
except StopIteration:
|
||||||
|
total_health = 0
|
||||||
|
for row in field:
|
||||||
|
for value in row:
|
||||||
|
if type(value) in (Elf, Goblin) and value.health > 0:
|
||||||
|
total_health += value.health
|
||||||
|
|
||||||
|
print("Rounds:", steps)
|
||||||
|
print("Health:", total_health)
|
||||||
|
print("Elf Deaths:", Elf.deaths)
|
||||||
|
print(total_health * steps)
|
||||||
|
break
|
||||||
|
|
||||||
|
steps += 1
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
main()
|
||||||
|
if Elf.deaths == 0:
|
||||||
|
print("yay")
|
||||||
|
break
|
||||||
|
|
||||||
|
Elf.power += 1
|
||||||
|
print("oh no :(, trying", Elf.power)
|
|
@ -0,0 +1,154 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t before[4];
|
||||||
|
uint8_t opcode;
|
||||||
|
uint8_t a, b, c;
|
||||||
|
uint8_t after[4];
|
||||||
|
} Sample;
|
||||||
|
|
||||||
|
int sample_read(Sample *sample, FILE *file) {
|
||||||
|
int read = 0;
|
||||||
|
read +=
|
||||||
|
fscanf(file,
|
||||||
|
"Before: [%" SCNu8 ", %" SCNu8 ", %" SCNu8 ", %" SCNu8 "]\n",
|
||||||
|
&sample->before[0], &sample->before[1], &sample->before[2],
|
||||||
|
&sample->before[3]);
|
||||||
|
|
||||||
|
read += fscanf(file, "%" SCNu8 " %" SCNu8 " %" SCNu8 " %" SCNu8 "\n",
|
||||||
|
&sample->opcode, &sample->a, &sample->b, &sample->c);
|
||||||
|
|
||||||
|
read +=
|
||||||
|
fscanf(file,
|
||||||
|
"After: [%" SCNu8 ", %" SCNu8 ", %" SCNu8 ", %" SCNu8 "]\n\n",
|
||||||
|
&sample->after[0], &sample->after[1], &sample->after[2],
|
||||||
|
&sample->after[3]);
|
||||||
|
|
||||||
|
return read == 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sample_print(const Sample sample) {
|
||||||
|
printf(
|
||||||
|
"{\n"
|
||||||
|
" before: [%d, %d, %d, %d],\n"
|
||||||
|
" opcode: %d, a: %d, b: %d, c: %d,\n"
|
||||||
|
" after: [%d, %d, %d, %d]\n"
|
||||||
|
"}\n",
|
||||||
|
sample.before[0], sample.before[1], sample.before[2], sample.before[3],
|
||||||
|
sample.opcode, sample.a, sample.b, sample.c,
|
||||||
|
sample.after[0], sample.after[1], sample.after[2], sample.after[3]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sample_possible_opcodes(const Sample s) {
|
||||||
|
int possible_opcodes = 0;
|
||||||
|
|
||||||
|
// Addition
|
||||||
|
if (s.after[s.c] == s.before[s.a] + s.before[s.b]) {
|
||||||
|
printf("addr, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
if (s.after[s.c] == s.before[s.a] + s.b) {
|
||||||
|
printf("addi, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiplication
|
||||||
|
if (s.after[s.c] == s.before[s.a] * s.before[s.b]) {
|
||||||
|
printf("mulr, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
if (s.after[s.c] == s.before[s.a] * s.b) {
|
||||||
|
printf("muli, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bitwise AND
|
||||||
|
if (s.after[s.c] == (s.before[s.a] & s.before[s.b])) {
|
||||||
|
printf("banr, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
if (s.after[s.c] == (s.before[s.a] & s.b)) {
|
||||||
|
printf("bani, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bitwise OR
|
||||||
|
if (s.after[s.c] == (s.before[s.a] | s.before[s.b])) {
|
||||||
|
printf("borr, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
if (s.after[s.c] == (s.before[s.a] | s.b)) {
|
||||||
|
printf("bori, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assignment
|
||||||
|
if (s.after[s.c] == s.before[s.a]) {
|
||||||
|
printf("setr, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
if (s.after[s.c] == s.a) {
|
||||||
|
printf("seti, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Greater-than testing
|
||||||
|
if (s.after[s.c] == (s.a > s.before[s.b])) {
|
||||||
|
printf("gtir, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
if (s.after[s.c] == (s.before[s.a] > s.b)) {
|
||||||
|
printf("gtri, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
if (s.after[s.c] == (s.before[s.a] > s.before[s.b])) {
|
||||||
|
printf("gtrr, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equality testing
|
||||||
|
if (s.after[s.c] == (s.a == s.before[s.b])) {
|
||||||
|
printf("eqir, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
if (s.after[s.c] == (s.before[s.a] == s.b)) {
|
||||||
|
printf("eqri, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
if (s.after[s.c] == (s.before[s.a] == s.before[s.b])) {
|
||||||
|
printf("eqrr, ");
|
||||||
|
possible_opcodes += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return possible_opcodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("Usage: %s [input]\n", argv[0]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *file = fopen(argv[1], "r");
|
||||||
|
Sample sample = {0};
|
||||||
|
|
||||||
|
int gt3 = 0, samples = 0;
|
||||||
|
while (sample_read(&sample, file)) {
|
||||||
|
sample_print(sample);
|
||||||
|
int possible_opcodes = sample_possible_opcodes(sample);
|
||||||
|
printf("%d possible opcodes.\n\n", possible_opcodes);
|
||||||
|
if (possible_opcodes >= 3) {
|
||||||
|
gt3 += 1;
|
||||||
|
}
|
||||||
|
samples += 1;
|
||||||
|
}
|
||||||
|
printf("%d samples\n", samples);
|
||||||
|
printf("%d\n", gt3);
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1,194 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t opcode;
|
||||||
|
uint32_t a, b, c;
|
||||||
|
} Instruction;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t before[4];
|
||||||
|
Instruction instruction;
|
||||||
|
uint32_t after[4];
|
||||||
|
} Sample;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ADDR, ADDI, MULR, MULI,
|
||||||
|
BANR, BANI, BORR, BORI,
|
||||||
|
SETR, SETI, GTIR, GTRI,
|
||||||
|
GTRR, EQIR, EQRI, EQRR,
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *names[] = {
|
||||||
|
"addr", "addi", "mulr", "muli",
|
||||||
|
"banr", "bani", "borr", "bori",
|
||||||
|
"setr", "seti", "gtir", "gtri",
|
||||||
|
"gtrr", "eqir", "eqri", "eqrr",
|
||||||
|
};
|
||||||
|
|
||||||
|
uint16_t table[16] = {
|
||||||
|
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
|
||||||
|
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
|
||||||
|
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
|
||||||
|
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
|
||||||
|
};
|
||||||
|
|
||||||
|
int opcodes[16];
|
||||||
|
|
||||||
|
int sample_read(Sample *s, FILE *file) {
|
||||||
|
int read = 0;
|
||||||
|
|
||||||
|
read =
|
||||||
|
fscanf(file, "Before: [%u, %u, %u, %u]\n",
|
||||||
|
&s->before[0], &s->before[1], &s->before[2], &s->before[3]);
|
||||||
|
if (read != 4) return 0;
|
||||||
|
|
||||||
|
Instruction *i = &s->instruction;
|
||||||
|
read = fscanf(file, "%" SCNu8 " %u %u %u\n",
|
||||||
|
&i->opcode, &i->a, &i->b, &i->c);
|
||||||
|
if (read != 4) return 0;
|
||||||
|
|
||||||
|
read =
|
||||||
|
fscanf(file, "After: [%u, %u, %u, %u]\n\n",
|
||||||
|
&s->after[0], &s->after[1], &s->after[2], &s->after[3]);
|
||||||
|
if (read != 4) return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t sample_possible_opcodes(const Sample s) {
|
||||||
|
uint16_t possible_opcodes = 0;
|
||||||
|
|
||||||
|
Instruction i = s.instruction;
|
||||||
|
// Addition
|
||||||
|
if (s.after[i.c] == s.before[i.a] + s.before[i.b]) possible_opcodes |= 1 << ADDR;
|
||||||
|
if (s.after[i.c] == s.before[i.a] + i.b) possible_opcodes |= 1 << ADDI;
|
||||||
|
// Multiplication
|
||||||
|
if (s.after[i.c] == s.before[i.a] * s.before[i.b]) possible_opcodes |= 1 << MULR;
|
||||||
|
if (s.after[i.c] == s.before[i.a] * i.b) possible_opcodes |= 1 << MULI;
|
||||||
|
// Bitwise AND
|
||||||
|
if (s.after[i.c] == (s.before[i.a] & s.before[i.b])) possible_opcodes |= 1 << BANR;
|
||||||
|
if (s.after[i.c] == (s.before[i.a] & i.b)) possible_opcodes |= 1 << BANI;
|
||||||
|
// Bitwise OR
|
||||||
|
if (s.after[i.c] == (s.before[i.a] | s.before[i.b])) possible_opcodes |= 1 << BORR;
|
||||||
|
if (s.after[i.c] == (s.before[i.a] | i.b)) possible_opcodes |= 1 << BORI;
|
||||||
|
// Assignment
|
||||||
|
if (s.after[i.c] == s.before[i.a]) possible_opcodes |= 1 << SETR;
|
||||||
|
if (s.after[i.c] == i.a) possible_opcodes |= 1 << SETI;
|
||||||
|
// Greater-than testing
|
||||||
|
if (s.after[i.c] == (i.a > s.before[i.b])) possible_opcodes |= 1 << GTIR;
|
||||||
|
if (s.after[i.c] == (s.before[i.a] > i.b)) possible_opcodes |= 1 << GTRI;
|
||||||
|
if (s.after[i.c] == (s.before[i.a] > s.before[i.b])) possible_opcodes |= 1 << GTRR;
|
||||||
|
// Equality testing
|
||||||
|
if (s.after[i.c] == (i.a == s.before[i.b])) possible_opcodes |= 1 << EQIR;
|
||||||
|
if (s.after[i.c] == (s.before[i.a] == i.b)) possible_opcodes |= 1 << EQRI;
|
||||||
|
if (s.after[i.c] == (s.before[i.a] == s.before[i.b])) possible_opcodes |= 1 << EQRR;
|
||||||
|
|
||||||
|
return possible_opcodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bits_set(uint16_t n) {
|
||||||
|
int bit = -1;
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
if ((n >> i) & 1) {
|
||||||
|
if (bit != -1) return -1;
|
||||||
|
bit = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void find_opcodes() {
|
||||||
|
int unknown = 16;
|
||||||
|
while (unknown > 0) {
|
||||||
|
for (int opcode = 0; opcode < 16; opcode++) {
|
||||||
|
int bit = bits_set(table[opcode]);
|
||||||
|
if (bit == -1) continue;
|
||||||
|
|
||||||
|
// Set every row in this column to 0
|
||||||
|
for (int j = 0; j < 16; j++)
|
||||||
|
table[j] &= ~(1 << bit);
|
||||||
|
|
||||||
|
opcodes[opcode] = bit;
|
||||||
|
unknown -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
printf("%d: %s\n", i, names[opcodes[i]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int instruction_read(Instruction *i, FILE *file) {
|
||||||
|
return fscanf(file, "%" SCNu8 " %u %u %u\n",
|
||||||
|
&i->opcode, &i->a, &i->b, &i->c) == 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void instruction_execute(const Instruction *i, uint32_t *r) {
|
||||||
|
switch (opcodes[i->opcode]) {
|
||||||
|
// Addition
|
||||||
|
case ADDR: r[i->c] = r[i->a] + r[i->b]; break;
|
||||||
|
case ADDI: r[i->c] = r[i->a] + i->b; break;
|
||||||
|
|
||||||
|
// Multiplication
|
||||||
|
case MULR: r[i->c] = r[i->a] * r[i->b]; break;
|
||||||
|
case MULI: r[i->c] = r[i->a] * i->b; break;
|
||||||
|
|
||||||
|
// Bitwise AND
|
||||||
|
case BANR: r[i->c] = (r[i->a] & r[i->b]); break;
|
||||||
|
case BANI: r[i->c] = (r[i->a] & i->b); break;
|
||||||
|
|
||||||
|
// Bitwise OR
|
||||||
|
case BORR: r[i->c] = (r[i->a] | r[i->b]); break;
|
||||||
|
case BORI: r[i->c] = (r[i->a] | i->b); break;
|
||||||
|
|
||||||
|
// Assignment
|
||||||
|
case SETR: r[i->c] = r[i->a]; break;
|
||||||
|
case SETI: r[i->c] = i->a; break;
|
||||||
|
|
||||||
|
// Greater-than testing
|
||||||
|
case GTIR: r[i->c] = (i->a > r[i->b]); break;
|
||||||
|
case GTRI: r[i->c] = (r[i->a] > i->b); break;
|
||||||
|
case GTRR: r[i->c] = (r[i->a] > r[i->b]); break;
|
||||||
|
|
||||||
|
// Equality testing
|
||||||
|
case EQIR: r[i->c] = (i->a == r[i->b]); break;
|
||||||
|
case EQRI: r[i->c] = (r[i->a] == i->b); break;
|
||||||
|
case EQRR: r[i->c] = (r[i->a] == r[i->b]); break;
|
||||||
|
|
||||||
|
default: assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("Usage: %s [input]\n", argv[0]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *file = fopen(argv[1], "r");
|
||||||
|
Sample sample = {0};
|
||||||
|
|
||||||
|
while (sample_read(&sample, file)) {
|
||||||
|
uint16_t possible_opcodes = sample_possible_opcodes(sample);
|
||||||
|
table[sample.instruction.opcode] &= possible_opcodes;
|
||||||
|
}
|
||||||
|
find_opcodes();
|
||||||
|
|
||||||
|
uint32_t registers[4] = {0};
|
||||||
|
Instruction instruction = {0};
|
||||||
|
while (instruction_read(&instruction, file)) {
|
||||||
|
const char *name = names[opcodes[instruction.opcode]];
|
||||||
|
printf("opcode: %2d (%s), a: %d, b: %d, c: %d\n", instruction.opcode,
|
||||||
|
name, instruction.a, instruction.b, instruction.c);
|
||||||
|
instruction_execute(&instruction, registers);
|
||||||
|
printf("registers: %d %d %d %d\n", registers[0], registers[1],
|
||||||
|
registers[2], registers[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
Loading…
Reference in New Issue