Example #1
0
    def test_reset(self):
        """
        Tests for CPU reset
        """
        e = ElfCPU()
        e.load_string('1,0,0,0,99')
        e.execute()
        e.reset()

        # Halted gets cleared
        self.assertFalse(e.is_halted)
        # Program counter goes to 0
        self.assertEqual(e.pc, 0)
        # Memory gets wiped so address 1 becomes invalid
        with self.assertRaises(ValueError):
            e.peek(1)
Example #2
0
 def test_halt(self):
     """
     Tests for the halt op code
     """
     e = ElfCPU()
     e.load_string('1,0,0,0,99')
     e.step()
     self.assertFalse(e.is_halted)
     e.step()
     self.assertTrue(e.is_halted)
Example #3
0
 def test_invalid_instr(self):
     """
     Tests for invalid op code
     """
     e = ElfCPU()
     e.load_string('123456789')
     with self.assertRaises(InvalidInstructionError):
         e.execute()
Example #4
0
 def test_gpf(self):
     """
     Tests for a general protection fault by allowing the program counter to
     go past the end of the memory
     """
     e = ElfCPU()
     e.load_string('1,0,0,0')
     with self.assertRaises(ProtectionFaultError):
         e.execute()
Example #5
0
 def test_load_string_types(self):
     """
     Checks for TypeError
     """
     e = ElfCPU()
     with self.assertRaises(TypeError):
         # noinspection PyTypeChecker
         e.load_string(0)
     e.load_string('1,2,3,4')
Example #6
0
    def test_op_add(self):
        """
        Tests ADD op code
        [dst]:=[a]+[b]
        """
        e = ElfCPU()
        # Invalid address 44 for a
        e.load_string('1,44,0,0')
        with self.assertRaises(ProtectionFaultError):
            e.step()

        # Invalid address 44 for b
        e.load_string('1,0,44,0')
        with self.assertRaises(ProtectionFaultError):
            e.step()

        # Invalid address 44 for dst
        e.load_string('1,0,0,44')
        with self.assertRaises(ProtectionFaultError):
            e.step()

        # 1 + 1 = 2 @ address 0
        e.load_string('1,0,0,0,99')
        e.step()
        self.assertEqual(e.peek(0), 2)

        # 2**64 + 1 = 1 @ address 0 (overflow and wrap)
        #e.load_string('1,5,6,0,99,'+str(2**64)+',1')
        #e.step()
        #self.assertEqual(e.peek(0), 1)

        # dst:=a+[b]
        e.load_string('101,44,5,6,99,2,-1')
        e.execute()
        self.assertEqual(e.peek(6), 46)

        # dst:=[a]+b
        e.load_string('1001,5,50,6,99,2,-1')
        e.execute()
        self.assertEqual(e.peek(6), 52)

        # dst:=a+b
        e.load_string('1101,5,5,6,99,2,-1')
        e.execute()
        self.assertEqual(e.peek(6), 10)
Example #7
0
    def test_poke(self):
        """
        Tests address range and data for poke
        """
        e = ElfCPU()
        e.load_string('0,1,2,3,4,5,6,7,8,9')

        # Address
        with self.assertRaises(TypeError):
            # noinspection PyTypeChecker
            e.poke('x', 2)
        with self.assertRaises(ValueError):
            e.poke(20, 2)
        with self.assertRaises(ValueError):
            e.poke(-1, 2)

        # Value
        with self.assertRaises(ValueError):
            e.poke(0, 2**64 + 1)

        self.assertEqual(e.poke(0, 99), 99)
        self.assertEqual(e.poke(9, 88), 88)
        self.assertEqual(e.peek(0), 99)
        self.assertEqual(e.peek(9), 88)
Example #8
0
    def test_peek(self):
        """
        Tests address range for peek
        """
        e = ElfCPU()
        e.load_string('0,1,2,3,4,5,6,7,8,9')
        with self.assertRaises(TypeError):
            # noinspection PyTypeChecker
            e.peek('x')
        with self.assertRaises(ValueError):
            e.peek(20)
        with self.assertRaises(ValueError):
            e.peek(-1)

        self.assertEqual(e.peek(0), 0)
        self.assertEqual(e.peek(9), 9)
Example #9
0
    def test_op_eq(self):
        """
        Tests equals op code
        """

        e = ElfCPU()
        """
        Tests if value of address 5 (10) is equal to value
        of address 6 (10).  Since this is true, write 1 to
        address 7.
        """
        e.load_string('8,5,6,7,99,10,10,-1')
        e.execute()
        self.assertEqual(e.peek(7), 1)
        """
        Tests if value of address 5 (10) is equal to value
        of address 6 (0).  Since this is false, write 0 to
        address 7.
        """
        e.load_string('8,5,6,7,99,10,0,-1')
        e.execute()
        self.assertEqual(e.peek(7), 0)
        """
        Tests if immediate value 10 is equal to immediate value
        10.  Since this is true, write 1 to address 7.
        """
        e.load_string('1108,10,10,7,99,2,3,-1')
        e.execute()
        self.assertEqual(e.peek(7), 1)
        """
        Tests if immediate value of 0 is equal to immediate value
        10.  Since this is false, write 0 to address 7.
        """
        e.load_string('1108,0,10,7,99,2,3,-1')
        e.execute()
        self.assertEqual(e.peek(7), 0)
Example #10
0
 def test_op_cmp_lessthan(self):
     """
     Tests compare less than op code
     """
     e = ElfCPU()
     """
     Tests if value of address 5 (5) is less than value of
     address 6 (10).  Since this is true write 1 to address 7.
     """
     e.load_string('7,5,6,7,99,5,10,-1')
     e.execute()
     self.assertEqual(e.peek(7), 1)
     """
     Tests if value of address 5 (10) is less than value of
     address 6 (5).  Since this is false write 0 to address 7.
     """
     e.load_string('7,5,6,7,99,10,5,-1')
     e.execute()
     self.assertEqual(e.peek(7), 0)
     """
     Tests if immediate value of 5 is less than immediate value of
     10.  Since this is true write 1 to address 7.
     """
     e.load_string('1107,5,10,7,99,0,0,-1')
     e.execute()
     self.assertEqual(e.peek(7), 1)
     """
     Tests if immediate value of 10 is less than immediate value of
     5.  Since this is false write 0 to address 7.
     """
     e.load_string('1107,10,5,7,99,0,0,-1')
     e.execute()
     self.assertEqual(e.peek(7), 0)
Example #11
0
    def test_op_jmp_true(self):
        """
        Tests jump if true op code
        """

        e = ElfCPU()
        """
        Tests address 8 (which is 1) if it is non-zero.  Since this is
        true, it jumps to the value of address 9 (which is 7).  This
        terminates the program.
        """
        e.load_string('5,8,9,1101,1,1,8,99,1,7')
        e.execute()
        self.assertEqual(e.peek(8), 1)
        """
        Tests immediate value 8 if it is non-zero.  Since it is
        true, jump to immediate address 7 which terminates.
        """
        e.load_string('1105,8,7,1101,1,1,8,99,1,7')
        e.execute()
        self.assertEqual(e.peek(8), 1)
        """
        Tests address 8 (which is 0) if it is non-zero.  Since this is
        false it does not jump and instead adds 1+1 to address 8.
        """
        e.load_string('5,8,9999,1101,1,1,8,99,0,7')
        e.execute()
        self.assertEqual(e.peek(8), 2)
        """
        Tests immediate value 0 if it is non-zero.  Since it is
        false it does not jump and instead adds 1+1 to address 8. 
        """
        e.load_string('1105,0,9999,1101,1,1,8,99,0,7')
        e.execute()
        self.assertEqual(e.peek(8), 2)
Example #12
0
    def test_op_output(self):
        """
        Tests output op code

        Use io.StringIO() to capture the output
        """
        e = ElfCPU()

        # Interrupts off
        e.load_string('4,5,104,66,99,55')
        e.interrupts = False

        result = None
        with patch('sys.stdout', new=io.StringIO()) as output:
            e.execute()
            result = output.getvalue()
        result = result.splitlines()

        # First is a reference to memory address 5
        self.assertEqual(result[0].strip(), '55')
        # Second is an immediate value
        self.assertEqual(result[1].strip(), '66')

        # Interrupts on

        e.load_string('4,5,104,66,99,55')
        e.interrupts = True

        with self.assertRaises(OutputInterrupt):
            e.execute()
        self.assertEqual(e.output_buffer, 55)
        # Don't clear buffer
        with self.assertRaises(OutputOverflow):
            e.execute()

        # Restart test
        e.reset()
        e.load_string('4,5,104,66,99,55')
        e.interrupts = True

        with self.assertRaises(OutputInterrupt):
            e.execute()
        self.assertEqual(e.output_buffer, 55)

        # Clear buffer
        del e.output_buffer

        with self.assertRaises(OutputInterrupt):
            e.execute()
        self.assertEqual(e.output_buffer, 66)
Example #13
0
    def test_op_input(self):
        """
        Tests input op code

        Use unittest.mock.patch to fake the input value
        """
        e = ElfCPU()

        # Interrupts off
        e.load_string('3,3,99,-1')
        e.interrupts = False
        with patch('builtins.input', return_value='1234'):
            e.execute()
            self.assertEqual(e.peek(3), 1234)

        # Interrupts on
        e.load_string('3,5,3,5,99,-1')
        e.interrupts = True
        with self.assertRaises(InputInterrupt):
            e.step()

        # Should be back at pc = 0
        self.assertEqual(e.pc, 0)

        # Load input
        e.input_buffer = 567

        # Loading again overflows
        with self.assertRaises(InputOverflow):
            e.input_buffer = 123

        # Execute the input instruction
        e.step()
        self.assertEqual(e.peek(5), 567)

        # Exec next input instruction
        with self.assertRaises(InputInterrupt):
            e.step()

        e.input_buffer = 987

        # Execute until end
        e.execute()
        self.assertEqual(e.peek(5), 987)
Example #14
0
    def test_op_mul(self):
        """
        Tests MUL op code
        [dst]:=[a]*[b]
        """
        e = ElfCPU()
        # Invalid address 44 for a
        e.load_string('2,44,0,0')
        with self.assertRaises(ProtectionFaultError):
            e.step()

        # Invalid address 44 for b
        e.load_string('2,0,44,0')
        with self.assertRaises(ProtectionFaultError):
            e.step()

        # Invalid address 44 for dst
        e.load_string('2,0,0,44')
        with self.assertRaises(ProtectionFaultError):
            e.step()

        # 2 * 2 = 4 @ address 0
        e.load_string('2,0,0,0,99')
        e.step()
        self.assertEqual(e.peek(0), 4)

        # 2**63 * 3 = 9223372036854775808 @ address 0 (overflow and wrap)
        #e.load_string('2,5,6,0,99,' + str(2 ** 63) + ',3')
        #e.step()
        #self.assertEqual(e.peek(0), 9223372036854775808)

        # dst:=a*[b]
        e.load_string('102,44,5,6,99,2,-1')
        e.execute()
        self.assertEqual(e.peek(6), 88)

        # dst:=[a]*b
        e.load_string('1002,5,50,6,99,2,-1')
        e.execute()
        self.assertEqual(e.peek(6), 100)

        # dst:=a*b
        e.load_string('1102,5,5,6,99,2,-1')
        e.execute()
        self.assertEqual(e.peek(6), 25)
Example #15
0
waived worldwide under copyright law, including all related and
neighboring rights, to the extent allowed by law.

You may copy, modify, distribute, and perform the work, even for
commercial purposes, all without asking permission.  See the
accompanying COPYRIGHT document.
"""

from day7 import ElfCPU, InputInterrupt, OutputInterrupt, SystemHaltError
from itertools import permutations
"""
Part Two
"""

# Amps A through E
amplifiers = [ElfCPU() for _ in range(5)]

phases = permutations([5, 6, 7, 8, 9])

# Max thruster
thruster = 0

with open('input.txt') as f:
    intcode = ''.join(f.readlines())

# Iterate through phases
for phase in phases:
    # Prepare amps
    for amp in amplifiers:
        amp.reset()
        amp.load_string(intcode)
Example #16
0
NO COPYRIGHT
This work is dedicated to the public domain.  All rights have been
waived worldwide under copyright law, including all related and
neighboring rights, to the extent allowed by law.

You may copy, modify, distribute, and perform the work, even for
commercial purposes, all without asking permission.  See the
accompanying COPYRIGHT document.
"""

from day7 import ElfCPU, InputInterrupt, OutputInterrupt
from itertools import permutations
"""
Part One
"""
amp = ElfCPU()

phases = permutations([0, 1, 2, 3, 4])

# Max thruster
thruster = 0

with open('input.txt') as f:
    intcode = ''.join(f.readlines())

# Iterate through phases
for phase in phases:
    input_signal = 0
    # Iterate through amps
    for position in range(5):
        # Clear state