|
|
@@ -0,0 +1,286 @@
|
|
|
+def unbleach(n):
|
|
|
+ return n.replace(' ', 's').replace('\t', 't').replace('\n', 'n')
|
|
|
+
|
|
|
+
|
|
|
+# solution
|
|
|
+class White:
|
|
|
+
|
|
|
+ def __init__(self):
|
|
|
+ self.output = ''
|
|
|
+ self.stack = []
|
|
|
+ self.heap = {}
|
|
|
+ self.input = ''
|
|
|
+ self.index = 0
|
|
|
+ self.input_index = 0
|
|
|
+ self.input_list = []
|
|
|
+ self.instruction = []
|
|
|
+ self.input_str = ''
|
|
|
+ self.command = {' ': self.push_to_stack,
|
|
|
+ ' \t ': self.duplicate_value,
|
|
|
+ ' \t\n': self.discard_value,
|
|
|
+ ' \n ': self.duplicate_top,
|
|
|
+ ' \n\t': self.swap,
|
|
|
+ ' \n\n': self.discard_top,
|
|
|
+ '\t ': self.adding,
|
|
|
+ '\t \t': self.subtract,
|
|
|
+ '\t \n': self.multiple,
|
|
|
+ '\t \t ': self.division,
|
|
|
+ '\t \t\t': self.division_part,
|
|
|
+ '\t\t ': self.heap_store,
|
|
|
+ '\t\t\t': self.heap_pop,
|
|
|
+ '\t\n ': self.output_character,
|
|
|
+ '\t\n \t': self.output_number,
|
|
|
+ '\t\n\t ': self.read_char,
|
|
|
+ '\t\n\t\t': self.read_number,
|
|
|
+ '\n ': self.mark_location,
|
|
|
+ '\n \t': self.call_subroutine,
|
|
|
+ '\n \n': self.jump,
|
|
|
+ '\n\t ': self.jump_stack,
|
|
|
+ '\n\t\t': self.jump_stack_bzero,
|
|
|
+ '\n\t\n': self.subroutine_end,
|
|
|
+ '\n\n\n': self.end}
|
|
|
+ self.command_par = {' ': 0,
|
|
|
+ ' \t ': 0,
|
|
|
+ ' \t\n': 0,
|
|
|
+ '\n ': 1,
|
|
|
+ '\n \t': 1,
|
|
|
+ '\n \n': 1,
|
|
|
+ '\n\t ': 1,
|
|
|
+ '\n\t\t': 1}
|
|
|
+ self.error_marker = False
|
|
|
+ self.end = False
|
|
|
+
|
|
|
+ def parsing_code(self):
|
|
|
+ help_list = []
|
|
|
+ item_set = {' ', '\t', '\n'}
|
|
|
+ for i in range(len(self.input_str)):
|
|
|
+ if self.input_str[i] in item_set:
|
|
|
+ help_list.append(self.input_str[i])
|
|
|
+ self.input_str = ''.join(help_list)
|
|
|
+ while self.index < len(self.input_str) - 1:
|
|
|
+ help_str, i = '', 0
|
|
|
+ while self.index < len(self.input_str) and i < 5 and self.command.get(help_str) is None:
|
|
|
+ help_str = help_str + self.input_str[self.index]
|
|
|
+ i += 1
|
|
|
+ self.index += 1
|
|
|
+ if self.command.get(help_str) is None:
|
|
|
+ self.index = self.index - i
|
|
|
+ self.instruction.append(self.input_str[self.index])
|
|
|
+ self.index += 1
|
|
|
+ else:
|
|
|
+ self.instruction.append(help_str)
|
|
|
+ if self.command_par.get(help_str) is not None:
|
|
|
+ help_list = []
|
|
|
+ while self.input_str[self.index] != '\n':
|
|
|
+ help_list.append(self.input_str[self.index])
|
|
|
+ self.index += 1
|
|
|
+ if self.command_par[help_str] == 0:
|
|
|
+ self.instruction.append(self.parsing_number(help_list))
|
|
|
+ else:
|
|
|
+ self.instruction.append(self.parsing_label(help_list))
|
|
|
+ self.index += 1
|
|
|
+ self.index = 0
|
|
|
+
|
|
|
+ def parsing_label(self, container):
|
|
|
+ return ''.join(container)
|
|
|
+
|
|
|
+ def parsing_number(self, container):
|
|
|
+ number, place = 0, 0
|
|
|
+ while len(container) > 1:
|
|
|
+ x = container.pop()
|
|
|
+ if ord(x) == 9:
|
|
|
+ number += 2 ** place
|
|
|
+ place += 1
|
|
|
+ x = container.pop()
|
|
|
+ if ord(x) == 9:
|
|
|
+ number = -1 * number
|
|
|
+ return number
|
|
|
+
|
|
|
+ def command_check(self):
|
|
|
+ i = 0
|
|
|
+ while i < len(self.instruction):
|
|
|
+ if self.command.get(self.instruction[i]) is None:
|
|
|
+ raise Exception('Invalid command')
|
|
|
+ if self.command_par.get(self.instruction[i]) is not None:
|
|
|
+ i += 1
|
|
|
+ i += 1
|
|
|
+
|
|
|
+ def push_to_stack(self):
|
|
|
+ self.index += 1
|
|
|
+ self.stack.append(self.instruction[self.index])
|
|
|
+
|
|
|
+ def duplicate_value(self):
|
|
|
+ self.index += 1
|
|
|
+ if len(self.stack) - 1 < self.instruction[self.index]:
|
|
|
+ self.error_marker = True
|
|
|
+ value = self.stack[len(self.stack) - self.instruction[self.index] - 1]
|
|
|
+ self.stack.append(value)
|
|
|
+
|
|
|
+ def discard_value(self):
|
|
|
+ self.index += 1
|
|
|
+ value = self.stack.pop()
|
|
|
+ number = self.instruction[self.index]
|
|
|
+ if number < 0 or number >= len(self.stack):
|
|
|
+ self.stack = [value]
|
|
|
+ else:
|
|
|
+ for i in range(number):
|
|
|
+ self.stack.pop()
|
|
|
+ self.stack.append(value)
|
|
|
+
|
|
|
+ def duplicate_top(self):
|
|
|
+ value = self.stack[len(self.stack) - 1]
|
|
|
+ self.stack.append(value)
|
|
|
+
|
|
|
+ def swap(self):
|
|
|
+ a = self.stack.pop()
|
|
|
+ b = self.stack.pop()
|
|
|
+ self.stack.append(a)
|
|
|
+ self.stack.append(b)
|
|
|
+
|
|
|
+ def discard_top(self):
|
|
|
+ self.stack.pop()
|
|
|
+
|
|
|
+ def adding(self):
|
|
|
+ a = self.stack.pop()
|
|
|
+ b = self.stack.pop()
|
|
|
+ self.stack.append(a + b)
|
|
|
+
|
|
|
+ def subtract(self):
|
|
|
+ a = self.stack.pop()
|
|
|
+ b = self.stack.pop()
|
|
|
+ self.stack.append(b - a)
|
|
|
+
|
|
|
+ def multiple(self):
|
|
|
+ a = self.stack.pop()
|
|
|
+ b = self.stack.pop()
|
|
|
+ self.stack.append(b * a)
|
|
|
+
|
|
|
+ def division(self):
|
|
|
+ a = self.stack.pop()
|
|
|
+ b = self.stack.pop()
|
|
|
+ self.stack.append(b // a)
|
|
|
+
|
|
|
+ def division_part(self):
|
|
|
+ a = self.stack.pop()
|
|
|
+ b = self.stack.pop()
|
|
|
+ sign = a // abs(a)
|
|
|
+ return self.stack.append(sign * abs(b % a))
|
|
|
+
|
|
|
+ def heap_store(self):
|
|
|
+ a = self.stack.pop()
|
|
|
+ b = self.stack.pop()
|
|
|
+ self.heap[b] = a
|
|
|
+
|
|
|
+ def heap_pop(self):
|
|
|
+ a = self.stack.pop()
|
|
|
+ self.stack.append(self.heap[a])
|
|
|
+
|
|
|
+ def output_character(self):
|
|
|
+ self.output = self.output + chr(self.stack.pop())
|
|
|
+
|
|
|
+ def output_number(self):
|
|
|
+ self.output = self.output + str(self.stack.pop())
|
|
|
+
|
|
|
+ def read_char(self):
|
|
|
+ b = self.stack.pop()
|
|
|
+ self.heap[b] = ord(self.input[self.input_index])
|
|
|
+ self.input_index += 1
|
|
|
+
|
|
|
+ def read_number(self):
|
|
|
+ b = self.stack.pop()
|
|
|
+ number_list = []
|
|
|
+ while self.input_index < len(self.input) - 1 and self.input[self.input_index] != '\n':
|
|
|
+ number_list.append(self.input[self.input_index])
|
|
|
+ self.input_index += 1
|
|
|
+ self.input_index += 1
|
|
|
+ self.heap[b] = int(''.join(number_list))
|
|
|
+
|
|
|
+ def mark_location(self):
|
|
|
+ self.index += 1
|
|
|
+
|
|
|
+ def label_location_check(self, label):
|
|
|
+ quantity = 0
|
|
|
+ for i in range(len(self.instruction) - 1):
|
|
|
+ if self.instruction[i] == '\n ' and self.instruction[i + 1] == label:
|
|
|
+ quantity += 1
|
|
|
+ if quantity != 1:
|
|
|
+ raise ValueError('Unknown or repeated label')
|
|
|
+
|
|
|
+ def call_subroutine(self):
|
|
|
+ index_help, flag = 0, 0
|
|
|
+ while flag == 0:
|
|
|
+ if self.instruction[index_help] == '\n ' and self.instruction[index_help + 1] == self.instruction[
|
|
|
+ self.index + 1]:
|
|
|
+ flag = 1
|
|
|
+ index_help += 1
|
|
|
+ mem = self.index + 1
|
|
|
+ self.index = index_help + 1
|
|
|
+ while self.instruction[self.index] != '\n\t\n':
|
|
|
+ self.command[self.instruction[self.index]]()
|
|
|
+ self.index += 1
|
|
|
+ if self.instruction[self.index] == '\n\n\n':
|
|
|
+ self.end = True
|
|
|
+ break
|
|
|
+ self.index = mem
|
|
|
+
|
|
|
+ def jump(self):
|
|
|
+ self.label_location_check(self.instruction[self.index + 1])
|
|
|
+ index_help, flag = 0, 0
|
|
|
+ self.index += 1
|
|
|
+ while flag == 0:
|
|
|
+ if self.instruction[index_help] == '\n ' and self.instruction[index_help + 1] == self.instruction[
|
|
|
+ self.index]:
|
|
|
+ flag = 1
|
|
|
+ index_help += 1
|
|
|
+ self.index = index_help
|
|
|
+
|
|
|
+ def jump_stack(self):
|
|
|
+ self.label_location_check(self.instruction[self.index + 1])
|
|
|
+ a = self.stack.pop()
|
|
|
+ self.index += 1
|
|
|
+ if a == 0:
|
|
|
+ index_help, flag = 0, 0
|
|
|
+ while flag == 0:
|
|
|
+ if self.instruction[index_help] == '\n ' and self.instruction[index_help + 1] == self.instruction[
|
|
|
+ self.index]:
|
|
|
+ flag = 1
|
|
|
+ index_help += 1
|
|
|
+ self.index = index_help
|
|
|
+
|
|
|
+ def jump_stack_bzero(self):
|
|
|
+ self.label_location_check(self.instruction[self.index + 1])
|
|
|
+ a = self.stack.pop()
|
|
|
+ self.index += 1
|
|
|
+ if a < 0:
|
|
|
+ index_help, flag = 0, 0
|
|
|
+ while flag == 0:
|
|
|
+ if self.instruction[index_help] == '\n ' and (self.instruction[index_help + 1]
|
|
|
+ == self.instruction[self.index]):
|
|
|
+ flag = 1
|
|
|
+ index_help += 1
|
|
|
+ self.index = index_help
|
|
|
+
|
|
|
+ def subroutine_end(self):
|
|
|
+ self.index += 1
|
|
|
+
|
|
|
+ def end(self):
|
|
|
+ pass
|
|
|
+
|
|
|
+
|
|
|
+def whitespace(code, inp=''):
|
|
|
+ w = White()
|
|
|
+ w.input_str = code
|
|
|
+ w.input = inp
|
|
|
+ w.parsing_code()
|
|
|
+ w.command_check()
|
|
|
+ while w.instruction[w.index] != '\n\n\n':
|
|
|
+ w.command[w.instruction[w.index]]()
|
|
|
+ if w.error_marker is True:
|
|
|
+ raise Exception('stack index out of range')
|
|
|
+ if w.end is True:
|
|
|
+ return w.output
|
|
|
+ w.index += 1
|
|
|
+ return w.output
|
|
|
+
|
|
|
+with open('./WS/example.ws') as source:
|
|
|
+ print(whitespace(source.read()))
|