From 51aefec7e017d105deac889472a880af72a3c9b0 Mon Sep 17 00:00:00 2001 From: Paulo Custodio Date: Wed, 22 Dec 2021 19:15:45 +0000 Subject: Brainfuck interpreter --- challenge-001/paulo-custodio/brainfuck.py | 139 ++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 challenge-001/paulo-custodio/brainfuck.py diff --git a/challenge-001/paulo-custodio/brainfuck.py b/challenge-001/paulo-custodio/brainfuck.py new file mode 100644 index 0000000000..e7234692cd --- /dev/null +++ b/challenge-001/paulo-custodio/brainfuck.py @@ -0,0 +1,139 @@ +#!/usr/bin/python3 + +# Run brainfuck from input +# Addition to the language: # - comment, ignore rest of the line +# Option: -t - trace execution + +import sys +import getopt +import re + +TAPE_SIZE = 3000 +do_trace = False + +class TuringMachine: + def __init__(self, prog): + self.tape = [0 for x in range(TAPE_SIZE)] + self.ptr = 0 + self.prog = self.parse(prog) + self.ip = 0 + + def parse(self, prog): + prog = re.sub(r"#[^\n]*", "", prog) # remove comments + prog = re.sub(r"\s*", "", prog) # remove blanks + return prog + + def done(self): + return self.ip >= len(self.prog) + + def run(self): + while not self.done(): + self.step() + + def step(self): + global do_trace + + op, n = self.get_op() + if op=="+": + self.tape[self.ptr] = (self.tape[self.ptr] + n) & 0xff + elif op=="-": + self.tape[self.ptr] = (self.tape[self.ptr] - n) & 0xff + elif op=="<": + self.ptr -= n + if self.ptr < 0: + print("pointer beyond tape start") + sys.exit(1) + elif op==">": + self.ptr += n + if self.ptr < 0: + print("pointer beyond tape end") + sys.exit(1) + elif op==".": + print(chr(self.tape[self.ptr]), end="") + if do_trace: + print("") + elif op==",": + self.tape[self.ptr] = chr(sys.stdin.read(1)) + elif op=="[": + if self.tape[self.ptr]==0: + self.find_close() + elif op=="]": + if self.tape[self.ptr]!=0: + self.find_open() + else: + print("operation not supported:", op) + sys.exit(1) + + if do_trace: + print(op, end=" ") + if n!=1: + print(n, end=" ") + print("", end="\t") + for i in range(self.ptr+10): + if i==self.ptr: + print(f"[{self.tape[i]:3d}]", end="") + else: + print(f" {self.tape[i]:3d} ", end="") + print("") + + def get_op(self): + if self.ip > len(self.prog): + print("execution beyond program end") + sys.exit(1) + + op = self.prog[self.ip] + self.ip += 1 + n = 1 + if op in ('+', '-', '<', '>'): + while self.ip < len(self.prog) and self.prog[self.ip]==op: + self.ip += 1 + n += 1 + return op, n + + def find_close(self): + num_open = 1 + while num_open > 0: + op, n = self.get_op() + if op=='[': + num_open += 1 + elif op==']': + num_open -= 1 + + def find_open(self): + num_open = 1 + self.ip -= 2 # point to op before ] + while num_open > 0: + if self.ip < 0: + print("execution beyond program start") + sys.exit(1) + op = self.prog[self.ip] + if op==']': + num_open += 1 + elif op=='[': + num_open -= 1 + if num_open==0: + self.ip += 1 + return + self.ip -= 1 + +# parse command line options +try: + opts, args = getopt.getopt(sys.argv[1:], 't') +except getopt.GetoptError as err: + print(err) + sys.exit(1) +for o, a in opts: + if o=="-t": + do_trace = True + else: + print("unhandled option") + sys.exit(1) +if len(args)!=1: + print("Usage: brainfuck.py [-t] file") + sys.exit(1) +with open(args[0]) as f: + prog = "".join(f.readlines()) + +# initialize and run Tuting Machine +tm = TuringMachine(prog) +tm.run() -- cgit From 2fdb31d3b27d4d1809484091e5b36cfefdff5c6c Mon Sep 17 00:00:00 2001 From: Paulo Custodio Date: Thu, 23 Dec 2021 12:21:58 +0000 Subject: Add Perl and Python solutions to challenge 031 --- challenge-031/paulo-custodio/Makefile | 2 ++ challenge-031/paulo-custodio/README | 1 + challenge-031/paulo-custodio/perl/ch-1.pl | 19 +++++++++++++++++++ challenge-031/paulo-custodio/perl/ch-2.pl | 16 ++++++++++++++++ challenge-031/paulo-custodio/python/ch-1.py | 18 ++++++++++++++++++ challenge-031/paulo-custodio/python/ch-2.py | 13 +++++++++++++ challenge-031/paulo-custodio/t/test-1.yaml | 7 +++++++ challenge-031/paulo-custodio/t/test-2.yaml | 5 +++++ 8 files changed, 81 insertions(+) create mode 100644 challenge-031/paulo-custodio/Makefile create mode 100644 challenge-031/paulo-custodio/README create mode 100644 challenge-031/paulo-custodio/perl/ch-1.pl create mode 100644 challenge-031/paulo-custodio/perl/ch-2.pl create mode 100644 challenge-031/paulo-custodio/python/ch-1.py create mode 100644 challenge-031/paulo-custodio/python/ch-2.py create mode 100644 challenge-031/paulo-custodio/t/test-1.yaml create mode 100644 challenge-031/paulo-custodio/t/test-2.yaml diff --git a/challenge-031/paulo-custodio/Makefile b/challenge-031/paulo-custodio/Makefile new file mode 100644 index 0000000000..c3c762d746 --- /dev/null +++ b/challenge-031/paulo-custodio/Makefile @@ -0,0 +1,2 @@ +all: + perl ../../challenge-001/paulo-custodio/test.pl diff --git a/challenge-031/paulo-custodio/README b/challenge-031/paulo-custodio/README new file mode 100644 index 0000000000..87dc0b2fbd --- /dev/null +++ b/challenge-031/paulo-custodio/README @@ -0,0 +1 @@ +Solution by Paulo Custodio diff --git a/challenge-031/paulo-custodio/perl/ch-1.pl b/challenge-031/paulo-custodio/perl/ch-1.pl new file mode 100644 index 0000000000..7e96de6302 --- /dev/null +++ b/challenge-031/paulo-custodio/perl/ch-1.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl + +# Challenge 031 +# +# Task #1 +# Create a function to check divide by zero error without checking if the +# denominator is zero. + +use Modern::Perl; + +sub divide { + my($num, $den) = @_; + my $res = eval { $num / $den }; + return "division by zero trapped" if $@; + return $res; +} + +say divide(5, 2); +say divide(5, 0); diff --git a/challenge-031/paulo-custodio/perl/ch-2.pl b/challenge-031/paulo-custodio/perl/ch-2.pl new file mode 100644 index 0000000000..0647281291 --- /dev/null +++ b/challenge-031/paulo-custodio/perl/ch-2.pl @@ -0,0 +1,16 @@ +#!/usr/bin/perl + +# Challenge 031 +# +# Task #2 +# Create a script to demonstrate creating dynamic variable name, assign a value +# to the variable and finally print the variable. The variable name would be +# passed as command line argument. + +use Modern::Perl; +no strict 'refs'; + +my $name = shift || die "Usage: ch-2.pl name\n"; + +${$name} = 10; +say ${$name}; diff --git a/challenge-031/paulo-custodio/python/ch-1.py b/challenge-031/paulo-custodio/python/ch-1.py new file mode 100644 index 0000000000..6d380fde03 --- /dev/null +++ b/challenge-031/paulo-custodio/python/ch-1.py @@ -0,0 +1,18 @@ +#!/usr/bin/python3 + +# Challenge 031 +# +# Task #1 +# Create a function to check divide by zero error without checking if the +# denominator is zero. + +def divide(num, den): + try: + res = num / den + except ZeroDivisionError: + return "division by zero trapped" + else: + return res + +print(divide(5, 2 )) +print(divide(5, 0)) diff --git a/challenge-031/paulo-custodio/python/ch-2.py b/challenge-031/paulo-custodio/python/ch-2.py new file mode 100644 index 0000000000..eb5675143d --- /dev/null +++ b/challenge-031/paulo-custodio/python/ch-2.py @@ -0,0 +1,13 @@ +#!/usr/bin/python3 + +# Challenge 031 +# +# Task #2 +# Create a script to demonstrate creating dynamic variable name, assign a value +# to the variable and finally print the variable. The variable name would be +# passed as command line argument. + +import sys + +globals()[sys.argv[1]] = 10 +print(globals()[sys.argv[1]]) diff --git a/challenge-031/paulo-custodio/t/test-1.yaml b/challenge-031/paulo-custodio/t/test-1.yaml new file mode 100644 index 0000000000..7451f174a9 --- /dev/null +++ b/challenge-031/paulo-custodio/t/test-1.yaml @@ -0,0 +1,7 @@ +- setup: + cleanup: + args: + input: + output: | + 2.5 + division by zero trapped diff --git a/challenge-031/paulo-custodio/t/test-2.yaml b/challenge-031/paulo-custodio/t/test-2.yaml new file mode 100644 index 0000000000..7a099edf5c --- /dev/null +++ b/challenge-031/paulo-custodio/t/test-2.yaml @@ -0,0 +1,5 @@ +- setup: + cleanup: + args: name + input: + output: 10 -- cgit From c4bb1dec1a1fb2c69ce19643f4442e9139613d3b Mon Sep 17 00:00:00 2001 From: Paulo Custodio Date: Thu, 23 Dec 2021 12:23:42 +0000 Subject: Remove # comments, consider any char not recognized as a comment --- challenge-001/paulo-custodio/brainfuck.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/challenge-001/paulo-custodio/brainfuck.py b/challenge-001/paulo-custodio/brainfuck.py index e7234692cd..7ef3443113 100644 --- a/challenge-001/paulo-custodio/brainfuck.py +++ b/challenge-001/paulo-custodio/brainfuck.py @@ -1,14 +1,13 @@ #!/usr/bin/python3 # Run brainfuck from input -# Addition to the language: # - comment, ignore rest of the line # Option: -t - trace execution import sys import getopt import re -TAPE_SIZE = 3000 +TAPE_SIZE = 30000 do_trace = False class TuringMachine: @@ -19,8 +18,7 @@ class TuringMachine: self.ip = 0 def parse(self, prog): - prog = re.sub(r"#[^\n]*", "", prog) # remove comments - prog = re.sub(r"\s*", "", prog) # remove blanks + prog = re.sub(r"[^-+<>,.\[\]]+", "", prog) # remove non-brainfuck operations return prog def done(self): @@ -61,8 +59,7 @@ class TuringMachine: if self.tape[self.ptr]!=0: self.find_open() else: - print("operation not supported:", op) - sys.exit(1) + pass # ignore other characters if do_trace: print(op, end=" ") -- cgit