Package: ibdp-classes
IBDP Computer Science Pseudocode ClassesThe IB Computer Science documents,Approved notation for developing pseudocodeandPseudocode in Examinations, describe pseudocode and a set of limited-functionalityarray,collection,stackandqueuedata structure classes that may come up and be used in exams.This is a simple Python implementation of an IB pseudocode interpreter and the above restrictive classes, which can be used in programming activities to help familiarize students with the pseudocode and classes.Under the hood, the classes are simple wrappers over a Python list and the interpreter simply runs some perfunctory tests, translates pseudocode into (really ugly) Python and then does its best to execute the translation and generate helpful error messages.You can submitissues and requests here.Installpython -m pip install ibdp-classesInterpreting IB pseudocodeWe can use the library to interpret pseudocode. For example:example.pseudocodeoutput "Collection..."
ITEMS = new Collection(1, 2, 3)
ITEMS.resetNext()
loop while ITEMS.hasNext()
    X = ITEMS.getNext()
    output "X =", X
end loopAt the command line:python -m ibdp_classes example.pseudocodeOutput:Collection...
X = 1
X = 2
X = 3We can also interpret IB pseudocode from within a Python script by creating and calling aPseudocodeinstance. For example:importibdp_classesasibcode="""output "Array..."XS = new Array(1, 2, 3, 4, 5)N = 5loop I from 0 to N - 1output "xs[", I, "] = ", XS[I]end loop"""script=ib.Pseudocode(code)output=script()print(output)Output:Array...
xs[ 0 ] =  1
xs[ 1 ] =  2
xs[ 2 ] =  3
xs[ 3 ] =  4
xs[ 4 ] =  5Additions to IB pseudocodefunctionandprocedureIn exams, IB pseudocode typically usesoutputto display results, and either doesn't explicitly define functions or procedures, or else does so informally and inconsistently. I have thus addedfunctionandprocedurestructures to the pseudocode definitions.For example:function CONTAINS(NEEDLE, HAYSTACK, N)
    // Where NEEDLE is a string, HAYSTACK is an Array
    // of strings, and N is the length of HAYSTACK.
    FOUND = false
    loop K from 0 to N-1
        if HAYSTACK[K] = NEEDLE then
            FOUND = true
        end if
    end loop
    return FOUND
end function

HAYSTACK = new Array(20, -3, 5, 7, 2, 13, 12, 19)
output "HAYSTACK:", HAYSTACK

output "5 is in HAYSTACK?"
output CONTAINS(5, HAYSTACK, 8)

output "4 is in HAYSTACK?"
output CONTAINS(4, HAYSTACK, 8)Output:HAYSTACK: Array { 20, -3, 5, 7, 2, 13, 12, 19 }
5 is in HAYSTACK?
True
4 is in HAYSTACK?
FalseInput types usingasIn IBDP pseudocode, the keywordinputis used to generically collect input from the user, and context is used to determine whether the input should be interpreted as a string, integer or floating point number. I have addedas intandas floatas appendages to the input statement for when we want to be explicit.For example:output "Input an integer."
input COUNT as int

if COUNT mod 2 = 0 then
    output COUNT, "is even..."
else
    output COUNT, "is odd..."
end ifImporting functionalityIf we would like to give the pseudocode access to variables or functions defined in Python, we can pass the definitions as a dictionary when calling thePseudocodeinstance:fromrandomimportrandomfrommathimportfloorimportibdp_classesasibcode="""loop I from 1 to 10output I, ":", FLOOR(10 * RANDOM())end loop"""script=ib.Pseudocode(code)output=script({"FLOOR":floor,"RANDOM":random})print(output)Example output:1 : 5
2 : 1
3 : 9
4 : 9
5 : 7
6 : 0
7 : 4
8 : 1
9 : 7
10 : 0Alternatively, we can have the pseudocode in its own file and the definitions we want available in a separate Python file, and then set-defsto the name of the Python file when we interpret the pseudocode from the command line. For example:defs.pyfromrandomimportrandomfrommathimportfloorRANDOM=randomFLOOR=floorexample.pseudoloop I from 1 to 10
    output I, ":", FLOOR(10 * RANDOM())
end loopFrom the command line:python -m ibdp_classes -defs defs.py example.pseudoExample output:1 : 5
2 : 8
3 : 4
4 : 3
5 : 1
6 : 5
7 : 3
8 : 2
9 : 3
10 : 5ExtensionsIn addition to being able to add bespoke functionality using-defs, a few wrappers are available as extensions that are not defined by IB but that can be helpful in certain lesson scenarios. We can access these extensions using-extand passing a string of extensions we would like to expose the pseudocode to.Extensions available:stringsThestringsextension exposes the following functions, which can helpful in activities involving string searches and manipulation.SUBSTRING(STRING, START, END)The substring ofSTRINGstarting at indexSTART(inclusive) and ending at indexEND(exclusive).CHARACTER(STRING, INDEX)The character inSTRINGat indexINDEX.UPPERCASE(STRING)andLOWERCASE(STRING)The uppercase and lowercase respectively ofSTRING.REPLACE(STRING, OLD, NEW)A copy ofSTRINGwithOLDreplaced withNEW.CONTAINS(STRING, SUBSTRING)WhetherSUBSTRINGoccurs inSTRING.STRING_LENGTH(STRING)The length ofSTRING.REPEAT(STRING, N)A string consisting ofSTRINGrepeatedNtimes.mathThemathextension exposes the following constants and functions, which can be helpful in activities involving math problems.PIAn approximation ofπ.TO_DEGREES(X)ConvertsXradians to degrees.TO_RADIANS(X)ConvertsXdegrees to radians.SIN(X),COS(X)&TAN(X)The sine, cosine and tangent respectively ofX.ARCSIN(X),ARCCOS(X)&ARCTAN(X)The arcsine, arccosine and arctangent respectively ofX.EAn approximation ofe.LOG(X)The base 10 logarithm ofX.LN(X)The baseelogarithm ofX.LOG(X, B)The baseBlogarithm ofX.EXP(X)The exponential ofX.POWER(X, P)Xraised to the power ofP.SQUARE(X)The square ofX.SQUARE_ROOT(X)The square root ofX.Example:examples/extensions/sine.pseudoA = 30
N = 20

loop I from 0 to N - 1
    SPACES = (A * (SIN(I * 2 * PI / N) + 1))
    output REPEAT(" ", SPACES), "*"
end loopFrom the command line:python -m ibdp_classes -ext 'strings math' examples/extensions/sine.pseudoOutput:*
                                        *
                                                *
                                                       *
                                                           *
                                                             *
                                                           *
                                                       *
                                                *
                                        *
                               *
                     *
             *
      *
  *
 *
  *
      *
             *
                     *bitsThebitsextension exposes the following functions, which can be helpful in activities involving bit manipulation.SET_BIT(X, P)IntegerXwith bit at positionPset.UNSET_BIT(X, P)IntegerXwith bit at positionPunset.BIT_IS_SET(X, P)Whether the bit at positionPof integerXis set.BIT_AND(A, B),BIT_OR(A, B),BIT_XOR(A, B)Bitwise conjunction, disjunction and exclusive disjunction respectively of integersAandB.BIT_NOT_8(X),BIT_NOT_16(X)andBIT_NOT_32(X)Bitwise negation of integerXassuming 8, 16 or 32 bits respectively in the structureExample:examples/extensions/binary.pseudoTEMPLATE = "[7][6][5][4][3][2][1][0]"

output "Input an integer from 0 to 255."

input VALUE as int

loop I from 0 to 7
    BIT_TEMPLATE = REPLACE("[I]", "I", I)
    if BIT_IS_SET(VALUE, I) then
       TEMPLATE = REPLACE(TEMPLATE, BIT_TEMPLATE, 1)
    else
       TEMPLATE = REPLACE(TEMPLATE, BIT_TEMPLATE, 0)
    end if
end loop

output "In binary,", VALUE, "is:", TEMPLATEIn the command line:python -m ibdp_classes -ext 'strings bits' examples/extensions/binary.pseudoExample output:Input an integer from 0 to 255.
42
In binary, 42 is: 00101010turtleTheturtleextension exposes some of the functionality of the Python turtle module, which can be helpful in fun, beginner-friendly (and more advanced) programming activities. Seesrc/extensions/turtle_defs.pyfor details.Example:examples/extensions/fractal.pseudoprocedure FRACTAL(LENGTH, DEPTH)
    DISTANCE = LENGTH / 3
    if DEPTH = 0 then
        GO_FORWARD(DISTANCE)
        TURN_LEFT(60)
        GO_FORWARD(DISTANCE)
        TURN_RIGHT(120)
        GO_FORWARD(DISTANCE)
        TURN_LEFT(60)
        GO_FORWARD(DISTANCE)
    else
        FRACTAL(DISTANCE, DEPTH - 1)
        TURN_LEFT(60)
        FRACTAL(DISTANCE, DEPTH - 1)
        TURN_RIGHT(120)
        FRACTAL(DISTANCE, DEPTH - 1)
        TURN_LEFT(60)
        FRACTAL(DISTANCE, DEPTH - 1)
    end if
end procedure

WIDTH = 600
Y = -250

loop DEPTH from 1 to 3
   PEN_UP()
   SET_X(-WIDTH / 2)
   SET_Y(Y)
   PEN_DOWN()
   FRACTAL(WIDTH, DEPTH)
   Y = Y + 200
end loop

HIDE_TURTLE()
WAIT()At the command line:python -m ibdp_classes -ext turtle examples/extensions/fractal.pseudoOutput:Using the classes within Python scriptsThe classed defined by IB can be used directly in Python scripts. While there is not much of a use case for this, it might be helpful as an intermediate step in actually implementing pseudocode.For example:fromibdp_classesimportArraydefcontains(needle:int,haystack:Array[int],n:int)->bool:found=Falseforkinrange(n):ifhaystack[k]==needle:print("Found!")found=Truereturnfoundhaystack=Array(20,-3,5,7,2,13,12,19)print("haystack:",haystack)print("5 is in haystack?")print(contains(5,haystack,8))print("4 is in haystack?")print(contains(4,haystack,8))