2. Backtracking 2 step diagrams

The python file to make a 2-step backtracking diagram is below.
The 2 custom python modules required are:
The python file, backtracking_2step_diagram_maker.py, when run, will ask for these inputs:
Choose the type of diagrams:
"Enter 1, 2, 3, 4, 5 or 6 for standard, 1 row build expression, 1 row inverse operations, 1 row from expression, solve from expression, blank "
Choose the first arithmetic process:
"Enter 1, 2, 3, 4 or 5 for +, -, X, /, random for 1st process"
Choose the second arithmetic process:
"Enter 1, 2, 3, 4 or 5 for +, -, X, /, random for 2nd process"
Choose the file name base:
"Enter the base filename to be added to the prefix :"
The prefix will be “bt2” for standard; “bt2_build” for 1 row build expression; or “bt2_invop” for 1 row inverse operations.
The prefix will be “bt2_fromexp” for 1 row from expression; “bt2_solvefromexp” for solve from expression; or “bt2_blank” for blank.
The filename will have “_q” added for the question diagram and “_ans” for the answer diagram.

2.1. Example 2-step backtracking diagram

question

answer


2.2. Example 2-step backtracking diagram: 1 row; building the expression

question

answer


2.3. Example 2-step backtracking diagram: 1 row; inverse operations

question

answer


2.4. Example 2-step backtracking diagram: 1 row; from the expression

question

answer


2.5. Example 2-step backtracking diagram: solve from the expression

question

answer


2.6. Example 2-step backtracking diagram: blank

blank


2.7. 2-step backtracking diagram: python

  1from pathlib import Path
  2import subprocess
  3import time
  4import random
  5import magick_pdf_to_png
  6import backtracking_functions as btf
  7
  8currfile_dir = Path(__file__).parent
  9tex_template_path = currfile_dir / "backtrack_2step_template.tex"
 10texans_template_path = currfile_dir / "backtrack_2step_template.tex"
 11
 12tex_diagram_standard_template_path = (
 13    currfile_dir / "backtrack_2step_diagram_template.tex"
 14)
 15tex_diagram_buildexp_template_path = (
 16    currfile_dir / "backtrack_2step_diagram_template_1buildexp.tex"
 17)
 18tex_diagram_invop_template_path = (
 19    currfile_dir / "backtrack_2step_diagram_template_1invop.tex"
 20)
 21tex_diagram_fromexp_template_path = (
 22    currfile_dir / "backtrack_2step_diagram_template_1invop.tex"
 23)
 24tex_diagram_solvefromexp_template_path = (
 25    currfile_dir / "backtrack_2step_diagram_template.tex"
 26)
 27tex_diagram_blank_template_path = (
 28    currfile_dir / "backtrack_2step_diagram_template_blank.tex"
 29)
 30
 31
 32def convert_to_pdf(tex_path, currfile_dir, aux_path):
 33    """
 34    Converts a TeX file to PDF format using pdfLaTeX.
 35
 36    Args:
 37        tex_path (str): The path to the TeX file.
 38        currfile_dir (str): The path to the directory where the TeX file is located.
 39        aux_path (str): The path to the directory where auxiliary files will be stored.
 40
 41    Returns:
 42        subprocess.CompletedProcess: A subprocess.CompletedProcess object containing information about the completed process.
 43
 44    Raises:
 45        FileNotFoundError: If the TeX file does not exist.
 46        subprocess.CalledProcessError: If pdfLaTeX returns a non-zero exit code.
 47    """
 48    result = subprocess.run(
 49        [
 50            "pdfLaTeX",
 51            tex_path,
 52            "-output-directory",
 53            currfile_dir,
 54            "-aux-directory",
 55            aux_path,
 56        ],
 57        stdout=subprocess.PIPE,
 58    )
 59
 60
 61# % end modify values for backtracking
 62# tex_keys = ['stepAB','stepABrev','stepBC', 'stepBCrev', boxA','boxB', 'boxC', 'boxCrev, 'boxBrev', 'boxArev' ]
 63# used by standard, build expression, inverse operations
 64tex_keys_q = ["stepAB", "stepBC", "boxA", "boxCrev"]
 65# used by from expression
 66tex_keys_q_fromexp = ["boxC"]
 67# used by from expression
 68tex_keys_q_solvefromexp = ["boxC", "boxCrev"]
 69
 70
 71def make1_diagram(tex_diagram_template_txt, num1, num2, tex_keys_q):
 72    tex_diagram_template_txt_ans = tex_diagram_template_txt
 73    kv = btf.get_2step_process_dict(num1, num2)
 74    for key, value in kv.items():
 75        tex_diagram_template_txt_ans = tex_diagram_template_txt_ans.replace(
 76            "<<" + key + ">>", value
 77        )
 78    for key, value in kv.items():
 79        if key in tex_keys_q:
 80            tex_diagram_template_txt = tex_diagram_template_txt.replace(
 81                "<<" + key + ">>", value
 82            )
 83        else:
 84            tex_diagram_template_txt = tex_diagram_template_txt.replace(
 85                "<<" + key + ">>", ""
 86            )
 87    return tex_diagram_template_txt, tex_diagram_template_txt_ans
 88
 89
 90def main():
 91    input_str = (
 92        "Enter 1, 2, 3, 4, 5 or 6 for standard, 1 row build expression, "
 93        + "1 row inverse operations, 1 row from expression, solve from expression, blank  \n"
 94    )
 95    bt_type = input(input_str)
 96    if bt_type.strip().isdigit():
 97        bt_type = int(bt_type)
 98        if not bt_type in [1, 2, 3, 4, 5, 6]:
 99            bt_type = 1  # standard by default
100    else:
101        bt_type = 1  # standard by default
102    #
103    if bt_type in [1, 2, 3, 4, 5]:
104        num1 = input("Enter 1, 2, 3, 4 or 5 for +, -, X, /, random for 1st process \n")
105        if num1.strip().isdigit():
106            num1 = int(num1)
107            if num1 not in [1, 2, 3, 4, 5]:
108                num1 = 5  # random by default
109        else:
110            num1 = 5  # random by default
111        #
112        num2 = input("Enter 1, 2, 3, 4 or 5 for +, -, X, /, random for 2nd process \n")
113        if num2.strip().isdigit():
114            num2 = int(num2)
115            if num2 not in [1, 2, 3, 4, 5]:
116                num2 = 5  # random by default
117        else:
118            num2 = 5  # random by default
119    else:
120        # use as placeholders for sake of call below; will end up returning + + dictionary but not used.
121        num1, num2 = None, None
122
123    match bt_type:
124        case 1:
125            tex_diagram_template_path = tex_diagram_standard_template_path
126            fileprefix = "bt2"
127            q_parts_to_fill = tex_keys_q
128        case 2:
129            tex_diagram_template_path = tex_diagram_buildexp_template_path
130            fileprefix = "bt2_build"
131            q_parts_to_fill = tex_keys_q
132        case 3:
133            tex_diagram_template_path = tex_diagram_invop_template_path
134            fileprefix = "bt2_invop"
135            q_parts_to_fill = tex_keys_q
136        case 4:
137            tex_diagram_template_path = tex_diagram_fromexp_template_path
138            fileprefix = "bt2_fromexp"
139            q_parts_to_fill = tex_keys_q_fromexp
140        case 5:
141            tex_diagram_template_path = tex_diagram_solvefromexp_template_path
142            fileprefix = "bt2_solvefromexp"
143            q_parts_to_fill = tex_keys_q_solvefromexp
144        case 6:
145            tex_diagram_template_path = tex_diagram_blank_template_path
146            fileprefix = "bt2_blank"
147            q_parts_to_fill = tex_keys_q
148    #
149    filename = input(
150        f"Enter the base filename to be added to the prefix {fileprefix}_: \n"
151    )
152    if not filename:
153        filename = "1"  # "bt2_1_q and bt2_1_ans as default file"
154    #
155    # set names of files that are made
156    # questions
157    tex_output_path = currfile_dir / f"{fileprefix}_{filename}_q.tex"
158    pdf_path = currfile_dir / f"{fileprefix}_{filename}_q.pdf"
159    png_path = currfile_dir / f"{fileprefix}_{filename}_q.png"
160    aux_path = currfile_dir / "temp"
161    # answers
162    tex_output_path_ans = currfile_dir / f"{fileprefix}_{filename}_ans.tex"
163    pdf_path_ans = currfile_dir / f"{fileprefix}_{filename}_ans.pdf"
164    png_path_ans = currfile_dir / f"{fileprefix}_{filename}_ans.png"
165
166    # Read in the LaTeX template file
167    with open(tex_template_path, "r") as infile:
168        tex_template_txt = infile.read()
169    # Read in the LaTeX template file for answers
170    with open(texans_template_path, "r") as infile:
171        tex_template_txt_ans = infile.read()
172    # Read in the LaTeX diagram template file
173    with open(tex_diagram_template_path, "r") as infile:
174        tex_diagram_template_txt = infile.read()
175
176    # Generate the <<diagram>> replacement tex
177    diagram_text, diagram_text_ans = make1_diagram(
178        tex_diagram_template_txt, num1, num2, q_parts_to_fill
179    )
180    # Replace the <<diagram>> placeholder in the LaTeX template
181    tex_template_txt = tex_template_txt.replace("<<diagram>>", diagram_text)
182    tex_template_txt_ans = tex_template_txt_ans.replace("<<diagram>>", diagram_text_ans)
183    # Write the question diagram tex to an output file
184    with open(tex_output_path, "w") as outfile:
185        outfile.write(tex_template_txt)
186    # Write the answer diagram tex to an output file
187    if bt_type in [1, 2, 3, 4, 5]:
188        with open(tex_output_path_ans, "w") as outfile:
189            outfile.write(tex_template_txt_ans)
190
191    # Wait for the files to be created
192    time.sleep(1)
193    # convert to pdf
194    convert_to_pdf(tex_output_path, currfile_dir, aux_path)
195    if bt_type in [1, 2, 3, 4, 5]:
196        convert_to_pdf(tex_output_path_ans, currfile_dir, aux_path)
197
198    # Wait for the files to be created
199    time.sleep(1)
200    # convert to png
201    magick_pdf_to_png.convert_pdf_to_png(pdf_path, png_path)
202    if bt_type in [1, 2, 3, 4, 5]:
203        magick_pdf_to_png.convert_pdf_to_png(pdf_path_ans, png_path_ans)
204
205
206if __name__ == "__main__":
207    print("starting")
208    main()
209    print("finished")