···2727# Work Environment & Company Preferences
2828292912. Do you prefer working in a startup, a large corporation, or a mid-sized company?
3030- - Not much preference here.
3030+ - I don't love corporate environments. I'd rather something mid size or smaller
313113. Do you want to work remotely, in-office, or in a hybrid setup?
3232 - Remotely or Hybrid
333314. What kind of work culture and values align with you?
+126
python/oct3/level4/getEvalSteps.py
···11+from typing import List
22+33+44+def getMostImportantOpIndex(parts: List[str]) -> int:
55+ """Returns the index of the most important operator in the given list of parts."""
66+ index = len(parts) + 1
77+ higher_order_operator = 0
88+99+ if "^" in parts:
1010+ higher_order_operator = 2
1111+ index = parts.index("^")
1212+ if "*" in parts and higher_order_operator < 2 and parts.index("*") < index:
1313+ higher_order_operator = 1
1414+ index = parts.index("*")
1515+ if "/" in parts and higher_order_operator < 2 and parts.index("/") < index:
1616+ higher_order_operator = 1
1717+ index = parts.index("/")
1818+ if "%" in parts and higher_order_operator < 2 and parts.index("%") < index:
1919+ higher_order_operator = 1
2020+ index = parts.index("%")
2121+ if "+" in parts and higher_order_operator < 1 and parts.index("+") < index:
2222+ index = parts.index("+")
2323+ if "-" in parts and higher_order_operator < 1 and parts.index("-") < index:
2424+ index = parts.index("-")
2525+ return index
2626+2727+2828+def runStep(a: str, sign: str, b: str) -> str:
2929+ """Runs a single step of the evaluation process."""
3030+ if sign == "+":
3131+ return str(int(a) + int(b))
3232+ elif sign == "-":
3333+ return str(int(a) - int(b))
3434+ elif sign == "*":
3535+ return str(int(a) * int(b))
3636+ elif sign == "/":
3737+ return str(int(a) // int(b))
3838+ elif sign == "%":
3939+ return str(int(a) % int(b))
4040+ elif sign == "^":
4141+ return str(int(a) ** int(b))
4242+ else:
4343+ raise ValueError("Invalid operator")
4444+4545+4646+def getEvalSteps(expr: str) -> str:
4747+ """Returns a string containing the evaluation steps of the given expression."""
4848+ padding = " " * (len(expr) + 1) + "= "
4949+5050+ expr = expr.strip()
5151+ expr = expr.replace(" ", "")
5252+ expr = expr.replace("**", "^")
5353+ expr = expr.replace("//", "/")
5454+ steps = [expr]
5555+5656+ expr_parts = []
5757+ cur_piece = ""
5858+ for c in expr:
5959+ if c.isdigit():
6060+ cur_piece += c
6161+ else:
6262+ expr_parts.append(cur_piece)
6363+ expr_parts.append(c)
6464+ cur_piece = ""
6565+ expr_parts.append(cur_piece)
6666+ while len(expr_parts) > 1:
6767+ next_op = getMostImportantOpIndex(expr_parts)
6868+ left = expr_parts.pop(next_op - 1)
6969+ op = expr_parts.pop(next_op - 1)
7070+ right = expr_parts.pop(next_op - 1)
7171+ val = runStep(left, op, right)
7272+ expr_parts.insert(next_op - 1, val)
7373+ steps.append("".join(expr_parts))
7474+ steps[0] = steps[0] + " = " + steps.pop(1)
7575+ steps = [step.replace("^", "**") for step in steps]
7676+ steps = [step.replace("/", "//") for step in steps]
7777+ steps = [padding + step if not i == 0 else step for i, step in enumerate(steps)]
7878+ final = "\n".join(steps) + "\n"
7979+ return final
8080+8181+8282+def testGetEvalSteps():
8383+ print("Testing getEvalSteps()...", end="")
8484+ assert (
8585+ getEvalSteps("2+3*4-8**3%3")
8686+ == """\
8787+2+3*4-8**3%3 = 2+3*4-512%3
8888+ = 2+12-512%3
8989+ = 2+12-2
9090+ = 14-2
9191+ = 12
9292+"""
9393+ )
9494+ assert (
9595+ getEvalSteps("2**2**3+4-2//3")
9696+ == """\
9797+2**2**3+4-2//3 = 4**3+4-2//3
9898+ = 64+4-2//3
9999+ = 64+4-0
100100+ = 68-0
101101+ = 68
102102+"""
103103+ )
104104+ assert (
105105+ getEvalSteps("4//2**2*8-3+2")
106106+ == """\
107107+4//2**2*8-3+2 = 4//4*8-3+2
108108+ = 1*8-3+2
109109+ = 8-3+2
110110+ = 5+2
111111+ = 7
112112+"""
113113+ )
114114+ assert (
115115+ getEvalSteps("2**4//2-3+1")
116116+ == """\
117117+2**4//2-3+1 = 16//2-3+1
118118+ = 8-3+1
119119+ = 5+1
120120+ = 6
121121+"""
122122+ )
123123+ print("Passed!")
124124+125125+126126+testGetEvalSteps()
+146
python/oct3/level4/runSimpleProgram.py
···11+from typing import List
22+33+44+def findLabel(lines: List[List[str]], label: str) -> int:
55+ """Find the line number of a label"""
66+ for i, line in enumerate(lines):
77+ if line[0] == label + ":":
88+ return i
99+ raise ValueError(f"Label '{label}' not found")
1010+1111+1212+def parse(args: List[int], values: List[int], arg: str) -> int:
1313+ """Parse an argument string into an integer value"""
1414+ arg_var = 0
1515+1616+ if arg.isdigit():
1717+ arg_var = int(arg)
1818+ elif arg.startswith("L"):
1919+ arg_var = values[int(arg[1:])]
2020+ elif arg.startswith("A"):
2121+ arg_var = args[int(arg[1:])]
2222+2323+ return arg_var
2424+2525+2626+def runL(args: List[int], values: List[int], line: List[str]):
2727+ """Run a Set command"""
2828+ out_var = int(line[0][1:])
2929+ op = line[1]
3030+3131+ if out_var >= len(values):
3232+ values.extend([0] * (out_var - len(values) + 1))
3333+3434+ if op.isdigit():
3535+ values[out_var] = int(op)
3636+ else:
3737+ op1, op2 = line[2], line[3]
3838+ op1_val, op2_val = parse(args, values, op1), parse(args, values, op2)
3939+ if op == "+":
4040+ values[out_var] = op1_val + op2_val
4141+ elif op == "-":
4242+ values[out_var] = op1_val - op2_val
4343+ else:
4444+ raise ValueError(f"Invalid Operator: {op}")
4545+4646+4747+def runJMP(args: List[int], values: List[int], line: List[str], lines) -> int | None:
4848+ """Return the target line number or None for a JMP command"""
4949+ command = line[0]
5050+ if command == "JMP":
5151+ jump_targ = line[1]
5252+ if jump_targ.isdigit():
5353+ target = int(line[1])
5454+ if target < 0 or target >= len(lines):
5555+ raise ValueError(f"Invalid Jump Target: {target}")
5656+ return target
5757+ else:
5858+ target = findLabel(lines, line[1])
5959+ if target < 0 or target >= len(lines):
6060+ raise ValueError(f"Invalid Jump Target: {target}")
6161+ return target
6262+ else:
6363+ expr = line[1]
6464+ if command[3] == "+":
6565+ var = int(expr[1])
6666+ if values[var] > 0:
6767+ target = findLabel(lines, line[2])
6868+ if target < 0 or target >= len(lines):
6969+ raise ValueError(f"Invalid Jump Target: {target}")
7070+ return target
7171+ return
7272+ elif command[3] == "0":
7373+ var = int(expr[1])
7474+ if values[var] == 0:
7575+ target = findLabel(lines, line[2])
7676+ if target < 0 or target >= len(lines):
7777+ raise ValueError(f"Invalid Jump Target: {target}")
7878+ return target
7979+ return
8080+ else:
8181+ raise ValueError(f"Invalid Jump Target: {line[0]}")
8282+8383+8484+def runSimpleProgram(program: str, args: List[int]):
8585+ """Run a simple program with given arguments."""
8686+ lines = program.splitlines()
8787+ lines = [line.strip() for line in lines if line.strip()]
8888+ lines = [line.split() for line in lines if not line.startswith("!")]
8989+9090+ values: List[int] = []
9191+ target = None
9292+ i = 0
9393+ return_value = None
9494+ while not return_value:
9595+ line = lines[i]
9696+ # print(f"executing {i}: {line}, L: {values}, A: {args}")
9797+ command = line[0]
9898+ if ":" in line or (target and target != i):
9999+ i += 1
100100+ continue
101101+ if target == i:
102102+ target = None
103103+ i += 1
104104+ if command.startswith("L"):
105105+ runL(args, values, line)
106106+ elif command.startswith("JMP"):
107107+ jump_to = runJMP(args, values, line, lines)
108108+ if jump_to != None:
109109+ i = jump_to
110110+ elif command == "RTN":
111111+ val = line[1]
112112+ # print(f"RTN {val} from A: {args}, L: {values}")
113113+ return_value = parse(args, values, val)
114114+ break
115115+ return return_value
116116+117117+118118+def testRunSimpleProgram():
119119+ print("Testing runSimpleProgram()...", end="")
120120+ largest = """! largest: Returns max(A0, A1)
121121+ L0 - A0 A1
122122+ JMP+ L0 a0
123123+ RTN A1
124124+ a0:
125125+ RTN A0"""
126126+ assert runSimpleProgram(largest, [5, 6]) == 6
127127+ assert runSimpleProgram(largest, [6, 5]) == 6
128128+129129+ sumToN = """! SumToN: Returns 1 + ... + A0
130130+ ! L0 is a counter, L1 is the result
131131+ L0 0
132132+ L1 0
133133+ loop:
134134+ L2 - L0 A0
135135+ JMP0 L2 done
136136+ L0 + L0 1
137137+ L1 + L1 L0
138138+ JMP loop
139139+ done:
140140+ RTN L1"""
141141+ assert runSimpleProgram(sumToN, [5]) == 1 + 2 + 3 + 4 + 5
142142+ assert runSimpleProgram(sumToN, [10]) == 10 * 11 // 2
143143+ print("Passed!")
144144+145145+146146+testRunSimpleProgram()