Тема: РАМ(рівнодоступна адресна машина)
Потрібно правила відкорегувати. Сижу цілий день, напевно око замилилось проблемою. Прошу допомогти
Код взятий з наукового посібника іноземного
import math
class SimpleComputer:
def __init__(self):
self.registers = [0] * 20 # Список регістрів розміром 20, ініціалізованих нулями
self.memory = [] # Пам'ять, список інструкцій, початково пустий
self.pc = 0 # Лічильник програмний (Program Counter), початково 0
self.halted = False # Прапорець, що показує, чи припинено виконання програми
def execute(self, program):
self.memory = program[:] # Копіюємо програму в пам'ять
self.pc = 0 # Починаємо з початку програми
self.halted = False # Знімаємо прапорець зупинки
while not self.halted:
instruction = self.memory[self.pc] # Беремо наступну інструкцію
op, *args = instruction # Розпаковуємо інструкцію, розділяючи опкод та аргументи
if op == 'READ': # Якщо опкод READ
self.registers[args[0]] = int(input()) # Записуємо вказане користувачем значення в регістр
self.pc += 1 # Переходимо до наступної інструкції
elif op == 'WRITE': # Якщо опкод WRITE
if str(args[0]).startswith('='): # Якщо аргумент починається з "=", то виводимо цифру
print(int(args[0][-1]))
else: # Інакше виводимо значення регістра
print(self.registers[args[0]])
self.pc += 1 # Переходимо до наступної інструкції
# Завантаження значення з пам'яті в регістр
elif op == 'LOAD':
if str(args[0]).startswith('='):
# Якщо аргумент починається з '=', то завантажуємо число, яке йде після '='
self.registers[0] = int(args[0][-1])
else:
# Якщо ні, то завантажуємо значення з пам'яті в регістр
self.registers[0] = self.registers[args[0]]
self.pc += 1
# Збереження значення з регістру в пам'ять
elif op == 'STORE':
self.registers[args[0]] = self.registers[0]
self.pc += 1
elif op == 'MULT':
# Множення значення з регістру на значення з пам'яті та збереження результату в регістр
self.registers[0] *= self.registers[args[0]]
self.pc += 1
elif op == 'ADD':
# Додавання значення з регістру до значення з пам'яті та збереження результату в регістр
if str(args[0]).startswith('='):
# Якщо аргумент починається з '=', то додаємо число, яке йде після '='
self.registers[0] += int(args[0][-1])
else:
# Якщо ні, то додаємо значення з пам'яті до значення в регістрі
self.registers[0] += self.registers[args[0]]
self.pc += 1
elif op == 'SUB':
# Віднімання значення з пам'яті від значення в регістрі та збереження результату в регістр
if str(args[0]).startswith('='):
# Якщо аргумент починається з '=', то віднімаємо число, яке йде після '='
self.registers[0] -= int(args[0][-1])
else:
# Якщо ні, то віднімаємо значення з пам'яті від значення в регістрі
self.registers[0] -= self.registers[args[0]]
self.pc += 1
elif op == 'JUMP':
# Перехід до певної комірки пам'яті
next_index = self.memory.index((args[0],))
if (next_index + 1) == len(self.memory):
# Якщо це остання комірка пам'яті, то pc необхідно встановити на поточну комірку
self.pc = next_index
else:
# Інакше на наступну комірку перехід
self.pc = next_index + 1
elif op == 'SWAP':
# Розділяємо аргументи та сортуємо регістри між ними
args = args[0].split()
print(sorted(self.registers[int(args[0]):int(args[1])]))
self.registers = self.registers[:int(args[0])] + sorted(
self.registers[int(args[0]):int(args[1])]) + self.registers[int(args[1]):]
print(self.registers)
# Збільшуємо лічильник команд на 1
self.pc += 1
elif op == 'COMPARE':
# Обчислюємо квадратний корінь з вказаного регістру та віднімаємо його з регістру 0
square = math.sqrt(self.registers[args[0]])
self.registers[0] -= square
# Збільшуємо лічильник команд на 1
self.pc += 1
elif op == 'JGTZ':
# Перевіряємо, чи значення регістру 0 більше за 0
if self.registers[0] > 0:
# Якщо так, то змінюємо значення лічильника команд на адресу вказану в аргументі та додаємо 1
self.pc = self.memory.index((args[0],)) + 1
else:
# Якщо ні, то просто збільшуємо лічильник команд на 1
self.pc += 1
elif op == 'JLTZ':
# Перевіряємо, чи значення регістру 0 менше за 0
if self.registers[0] < 0:
# Якщо так, то змінюємо значення лічильника команд на адресу вказану в аргументі та додаємо 1
self.pc = self.memory.index((args[0],)) + 1
else:
# Якщо ні, то просто збільшуємо лічильник команд на 1
self.pc += 1
# перевірка чи регістр 0 містить 0, якщо так - перехід на вказану адресу, інакше продовження виконання програми
elif op == 'JZERO':
if self.registers[0] == 0:
self.pc = self.memory.index((args[0],)) + 1
else:
self.pc += 1
# перевіряє, чи значення в регістрі 0 не дорівнює першому аргументу операції JNE.
elif op == 'JNE':
args = args[0].split()
if self.registers[0] != int(args[0]):
self.pc = self.memory.index((args[1],)) + 1
else:
self.pc += 1
# зупинка виконання програми
elif op == 'HALT':
break
# якщо операція невідома, просто переходимо до наступної інструкції
else:
self.pc += 1
Ось реалізація парсингу правил
from ram import SimpleComputer
# Написати програму для РАМ, яка читає n додатніх чисел, обмежених 0 і друкує їх у порядку неспадання.
program1 = [
('WHILE',),
('LOAD', 1),
('JLTZ', 'ENDWHILE'),
('LOAD', 1),
('SUB', '=1'),
('STORE', 1),
('READ', 0),
('STORE', 2),
('READ', 0),
('STORE', 3),
('READ', 0),
('STORE', 4),
('READ', 0),
('STORE', 5),
('READ', 0),
('STORE', 6),
('READ', 0),
('STORE', 7),
('JUMP', 'ENDWHILE'),
('JUMP', 'WHILE'),
('ENDWHILE',),
('SWAP', '2 7'),
('WRITE', 2),
('WRITE', 3),
('WRITE', 4),
('WRITE', 5),
('WRITE', 6),
('WRITE', 7),
('HALT',)]
# Написати програму для РАМ, яка допускає всі входи виду 1^n 2^n^n 0.
program2 = [
('LOAD', '=0'),
('STORE', 1),
('LOAD', '=0'),
('STORE', 2),
('LOAD', '=0'),
('STORE', 3),
('WHILE1',),
('READ', 0),
('JNE', '1 WHILE2'),
('LOAD', 1),
('ADD', '=1'),
('STORE', 1),
('JUMP', 'WHILE1'),
('WHILE2',),
('JNE', '2 WHILE3'),
('LOAD', 2),
('ADD', '=1'),
('STORE', 2),
('WHILE2CONTINUE',),
('READ', 0),
('JNE', '2 WHILE3'),
('LOAD', 2),
('ADD', '=1'),
('STORE', 2),
('JUMP', 'WHILE2CONTINUE'),
('WHILE3',),
('JNE', '0 FAIL'),
('LOAD', 3),
('ADD', '=1'),
('JNE', '1 FAIL'),
('LOAD', 1),
('COMPARE', 2),
('JZERO', 'SUCCESS'),
('FAIL',),
('WRITE', '=0'),
('JUMP', 'HALT'),
('SUCCESS',),
('WRITE', '=1'),
('HALT',)
]
# Написати програму для РАМ, яка обчислює n^n з часовою оцінкою О(log2n) при рівномірному ваговому критерії.
program3 = [
('READ', 0),
('LOAD', 0),
('JGTZ', 'POS'),
('WRITE', 0),
('JUMP', 'ENDIF'),
('POS',),
('LOAD', 0),
('STORE', 1),
('STORE', 3),
('LOAD', 0),
('SUB', '=1'),
('STORE', 2),
('WHILE',),
('LOAD', 2),
('JGTZ', 'CONTINUE'),
('JUMP', 'ENDWHILE'),
('CONTINUE',),
('LOAD', 1),
('MULT', 3),
('STORE', 1),
('LOAD', 2),
('SUB', '=1'),
('STORE', 2),
('JUMP', 'WHILE'),
('ENDWHILE',),
('WRITE', 1),
('ENDIF',),
('HALT',)
]
# Написати програму для РАМ із використанням непрямої адресації, яка вводить масив.
program4 = [
('WHILE',),
('LOAD', 1),
('JLTZ', 'ENDWHILE'),
('LOAD', 1),
('SUB', '=1'),
('STORE', 1),
('READ', 0),
('STORE', 2),
('READ', 0),
('STORE', 2 + 1),
('READ', 0),
('STORE', 2 + 2),
('READ', 0),
('STORE', 2 + 3),
('READ', 0),
('STORE', 2 + 4),
('READ', 0),
('STORE', 2 + 5),
('JUMP', 'ENDWHILE'),
('JUMP', 'WHILE'),
('ENDWHILE',),
('WRITE', 2),
('WRITE', 2 + 1),
('WRITE', 2 + 2),
('WRITE', 2 + 3),
('WRITE', 2 + 4),
('WRITE', 2 + 5),
('HALT',)
]
# Написати програму на РАМ, яка підраховує кількість від’ємних чисел на вході (подано n чисел)
program5 = [
('LOAD', '=0'),
('STORE', 1),
('READ', 0),
('SUB', '=1'),
('STORE', 2),
('WHILE',),
('LOAD', 2),
('JLTZ', 'ENDWHILE'),
('LOAD', 2),
('SUB', '=1'),
('STORE', 2),
('READ', 0),
('JGTZ', 'WHILE'),
('JZERO', 'WHILE'),
('LOAD', 1),
('ADD', '=1'),
('STORE', 1),
('JUMP', 'WHILE'),
('ENDWHILE',),
('WRITE', 1),
('HALT',)
]
RAM = SimpleComputer()
print("Task 1")
RAM.execute(program1)
print("Task 2")
RAM.execute(program2)
print("Task 3")
RAM.execute(program3)
print("Task 4")
RAM.execute(program4)
print("Task 5")
RAM.execute(program5)
Відповідно до умов завдання працює не дуже вдало! Help please
WHILE і тд це просто умовні мітки для кращої читабельності