Sunday, December 19, 2021

Using Spinoza with Python Objects (For in-class exercises)

During the COVID-19 pandemic, I started using Spinoza ( in Intro Programming.  Spinoza lets students try out solving problems in Python.  They get immediate feedback and there's lots of additional pedagogical features.

It uses Brython to run the code.  When it loads each page, parameters for functions are passed as strings.  If you try to create the objects in the Test Generator box, they won't pass correctly when Spinoza executes the tests.  Instead, you have to generate them using additional code that you put in the Solution box.  For example, if you're asking students to write a get_height() method or function for a Monkey class, you have to set things up this way:

  • Use a different name in the Method Name field.  I always just append "_wrapper" to the end.  (E.g. get_height_wrapper.)

  • For the number of parameters, use the total number of primitives you'll need to create any objects for the subject and all parameters.

  • Still put the original function/method header in the scaffolding box.  E.g. def get_height():  If they're writing a method, put it inside the class.  If there are other methods they'll need (__init__ or __str__) then you can include those here too.

class Monkey(object):

    '''Models a monkey.  Attributes: age, height, num_bananas.'''

    def get_height(self):


  • In the solution box, there are a bunch of additional things to do:

    • Add a function that creates an instance of the object:

def create_monkey(age, height, num_bananas):

    monkey = Monkey()

    monkey.age = age

    monkey.height = height

    monkey.num_bananas = bananas

    return monkey 

(This will change a lot if they've already created an __init__ and you include that in the scaffolding.)
    • If you didn't create the class above, create it here.  Also include any other classes you might need that you didn't put in the scaffolding.

    • Add the definition of the wrapper.  It should create the objects, then call the function/method that the student is writing.

def get_height_wrapper(age, height, num_bananas):

    monkey = create_monkey(age, height, num_bananas)

    return monkey.get_height()

    • Add your correct version of the requested function.  (E.g. my_get_height().)  If they're writing a method, you'll have to write this as a function instead.

def my_get_height(monkey):

    return monkey.height

    • Add the solution function, which does the same thing as the wrapper, except that it calls your function instead of the student's.

def solution(age, height, num_bananas):

    monkey = create_monkey(age, height, num_bananas)

    return my_get_height(monkey)

It took me a long time to get this working back in 2020, so I hope this is helpful for other people that want to use Spinoza!

Wednesday, August 25, 2021

A CGT Book for Undergrad Math Beginners

Craig Tennenhouse and I have finished the first version of our CGT book.  Here is the book's homepage.  We designed it to be used by undergraduates who may or may not be math majors.  That meant that we needed to include many discrete math concepts as well, to the point where Craig is currently using the text in his Discrete Math class as well.

I wanted this project to be a sabbatical project as early as eight years ago, in the spring of 2013, before I knew when my first sabbatical would be.  At that time I was teaching my third CGT course at Wittenberg University.  All three had been different: the first was as a Math/CS elective, the second was as a first-year college seminar course, and this third time was as an honors course for students with any major.  It was during this third time that I realized I wanted my own thorough notes with lots of exercises in them.  

I actually had some experience with text book exercises.  Nearly a decade prior, I worked with Otto Bretscher on the solution manual for his Linear Algebra text.  I wanted to have a similar large quantity of exercises so students could practice applying the concepts in a structured way.

I met Craig in the fall of 2013, and we have collaborated here and there since.  I had switched schools, which meant my future first sabbatical was far waylaid.  I got my feet under me at a new university, then, just a few years ago, I mentioned that I wanted to write my own book at a CGT event.  I explained that I wanted something at a bit lower level that would be more appropriate for general undergrads.  Craig asked whether we could write it together, which I was definitely on board with.  We both wanted a freely-downloadable book and I was excited to try and adapt my student/instructor dual mode LaTeX code so we could hide some of the exercise solutions.  (At this point, I don't think Craig realized just how many exercises I wanted to write.)

In the summer of 2019, we met and came up with a good outline.  Craig and I were on board with each others' ideas, such as doing impartial games before partisan, so things went very smoothly.  I used that outline in my sabbatical proposal for the spring semester of 2021.  That got accepted, then COVID-19 hit and Craig and I had to collaborate via video calls instead of in person.  (Our universities are about a 2 hour drive apart.)  We started writing in January, and we just finished enough for our first release. 

The result is a text book appropriate for either Discrete Math or Games.  For students who already know the introductory discrete topics, it's easy to skip those sections (laid out as Math Diversions).  There are over 400 exercises in the text, and about half of those have solutions in the back.  There are also some "Computational Corner" pieces with programming examples in Python.  

We aren't done.  We expect to make a bunch of updates as we improve things (and find errors).  The book will continue to get updated on the webpage.  The chaos of the pandemic caused a bunch of delays, so there are definitely many topics we didn't flesh out as much as we wanted.  Nevertheless, we are both very excited and look forward to hearing feedback from teachers, students, self-learners, and even people who just take a quick glance at the PDF.  We have a space in the book to thank contributors who point out errors we need to fix.  All kinds of feedback are very valuable!

I want to give an extra ``Thank You!'' to Craig, without whom this project would never have been completed.  I am so excited that we managed to get this done!

Please feel free to use the comments section here as one avenue to leave us feedback.