Parsons Problems

In a Parsons problem, users are provided with the lines / blocks of code and students must reorder them to create a solution.

Synopsis

The general format of the parsons directive is:

.. parsonsprob:: unique_id
   :options:

   + --- Content area ---
   |
   | one or more lines of instruction for the problem
   | -----
   | one or more lines of text
   | =====
   | grouped by
   | =====
   | five equals
   |
   + --------------------

Required Arguments

unique id
A unique identifier after a space and the :: in the title directive. Valid identifiers must not contain spaces. You should also avoid the characters `` ` , ``,, :, and *.
content area

A content block is required for a parsons problem. Place the question text after any directive options, if specified.

Use ----- to separate the question text from the code. The code should be specified in the correct order and indented properly. You can also group lines using ===== as in the problem below.

The code blocks will be shuffled randomly in the source area; press the Reset button on a problem to see this shuffling in action. To make the problem more difficult, you can enter distractors that are not part of the solution. These lines or blocks are marked by placing #distractor after the line. You can pair one or more distractors with a correct code block by marking it with #paired. When shuffled, paired blocks will be kept together with the correct code block.

Note

There is no space between the # and the distractor or paired

Optional Arguments

adaptive

Boolean. Offer to ‘adapt’, or simplify the problem after a few failed attempts. Default is false.

If specified, then this option will offer help after 3 failed attempts. After more failures, it will incrementally simplify the problem. It may remove indentation as part of the problem or remove distractors one at a time.

language

String. Set the language of the content area.

The default language is python. In a Parsons problem, the language is only used to control syntax highlighting.

The default language can be set in the book pavement.py file.

maxdist

Integer. Define a maximum number of distractors

If you specify distractors in the code, then this will specify the maximum number of distractors presented to the user.

noindent

Boolean. Do not mark against incorrect indentation.

If you do not want to force correct indentation, then this argument will indent blocks as you specify them. This makes the problem significantly easier to solve.

By default, code indentation matters. This is semantically meaningful in Python and good code practice in other programming languages. In the problem below, the third line needs to be indented to be correct.

.. parsonsprob:: pa-ex1

   Construct a block of code that correctly implements 
   the <b>accumulator</b> pattern.
   -----
   x = 0
   for i in range(10):
       x = x + 1
numbered

Enumerated. Turns on block numbering, either on the left or right.

Possible values are either left or right.

order

List. Define a specific ‘shuffled’ order

If you don’t want the code to be randomly shuffled, you can specify the order of the blocks in a comma-separated list (e.g., 0,5,3,2,4,1).

Languages supported

Any text is supported, however, syntax highlighting is supported for a limited number of programming languages. Syntax highlighting is supported for python, java, javascript, html, c, c++, ruby, and natural.

The language ‘natural’ is equivalent to ‘none’ in docutils, that is syntax highlighting is disabled.

Note

This directive uses ‘c++’ to refer to C++, whereas the activecode directive uses ‘cpp’.

Sphinx configuration options

The following options.build.template_args values can be set in a book pavement.py file.

language
The default language for parsons problem directives.

Internationalization

TBD.

Known limitations

The correct item to be paired with a #paired distraction must appear directly prior to the block marked #paired.

Once you have committed to using ==== to define groups of lines, then every line must be separated as groups.

All text in the content area is actually parsed as HTML. Sphinx markup is interpreted as plain text. Characters that have special meaning in HTML (<, >) need to be escaped in the directive text (&lt;, &gt;) unless surrounded by whitespace, for example:

# No space, HTML required
if x&lt;y:

# OK as is
if x > y:

# No space, HTML required
ArrayList&lt;Integer&gt; x = new ArrayList&lt;&gt;();

# OK as is
ArrayList < Integer > x = new ArrayList < > ();

Examples

The simplest parsons problems take each line of text, places each in its own parsons block, and assesses on both line order and indentation.

.. parsonsprob:: pa-ex1

   Construct a block of code that correctly implements 
   the <b>accumulator</b> pattern.
   -----
   x = 0
   for i in range(10):
       x = x + 1
        Ex-19-timed: Ex-18-timed: Construct a block of code that correctly implements
the accumulator pattern.x = 0
for i in range(10):
    x = x + 1
        
.. parsonsprob:: pa-ex1-cpp
   :language: c++

   Construct a block of code that correctly implements the accumulator pattern.
   -----
   template < class InputIt, class T >
   T sum(InputIt first, InputIt last, T value)
   {
       while (first != last) {
          value = value + *first;
          ++first;
       }
       return value;
   }
        Ex-21-timed: Ex-20-timed: Construct a block of code that correctly implements the accumulator pattern.template < class InputIt, class T >
T sum(InputIt first, InputIt last, T value)
{
    while (first != last) {
       value = value + *first;
       ++first;
    }
    return value;
}
        

Use the ===== markup in the content area to control parsons block definitions.

The default is to split each line of code into it’s own block.

.. parsonsprob:: par_ex_group1

   Construct a function that returns the max value from a list.
   -----
   def findmax(alist):
       if len(alist) == 0:
           return None
       curmax = alist[0]
       for item in alist:
           if item > curmax:
               curmax = item
       return curmax
        Ex-23-timed: Ex-22-timed: Construct a function that returns the max value from a list.def findmax(alist):
    if len(alist) == 0:
        return None
    curmax = alist[0]
    for item in alist:
        if item > curmax:
            curmax = item
    return curmax
        

If even 1 group is used, then all lines are interpreted as belonging to a group.

In order to have somelines stand alone, they must be placed in a group.

.. parsonsprob:: par_ex_group2

   Construct a function that returns the max value from a list.
   -----
   def findmax(alist):
   =====
       if len(alist) == 0:
           return None
   =====
       curmax = alist[0]
       for item in alist:
   =====
           if item > curmax:
   =====
               curmax = item
   =====
       return curmax
        Ex-25-timed: Ex-24-timed: Construct a function that returns the max value from a list.def findmax(alist):
---
    if len(alist) == 0:
        return None
---
    curmax = alist[0]
    for item in alist:
---
        if item > curmax:
---
            curmax = item
---
    return curmax
        
.. parsonsprob:: pa-ex-cpp-group
   :language: c++

   Construct a block of code that correctly implements the accumulator pattern.
   -----
   template&lt;class InputIt, class T&gt;
   =====
   T sum(InputIt first, InputIt last, T value)
   {
   =====
       while (first != last) {
   =====
          value = value + *first;
   =====
          ++first;
   =====
       }
       return value;
   =====
   }
        Ex-27-timed: Ex-26-timed: Construct a block of code that correctly implements the accumulator pattern.template<class InputIt, class T>
---
T sum(InputIt first, InputIt last, T value)
{
---
    while (first != last) {
---
       value = value + *first;
---
       ++first;
---
    }
    return value;
---
}
        

The numbered option sets block numbers.

.. parsonsprob:: par_ex_num_left
   :numbered: left

   Construct a function that returns the max value from a list.
   -----
   def findmax(alist):
   =====
       if len(alist) == 0:
           return None
   =====
       curmax = alist[0]
       for item in alist:
   =====
           if item > curmax:
   =====
               curmax = item
   =====
       return curmax
        Ex-29-timed: Ex-28-timed: Construct a function that returns the max value from a list.def findmax(alist):
---
    if len(alist) == 0:
        return None
---
    curmax = alist[0]
    for item in alist:
---
        if item > curmax:
---
            curmax = item
---
    return curmax
        

The maxdist option limits the number of distractors.

This example also demonstrates the use of adaptive option that will attempt to simplify the problem by removing distractors and helping with indentation after 3 failed attempts.

The adaptive option also adds a ‘Help Me’ button used to start the assistance. Adaptive behaviors do not kick in automatically, but only on request.

.. parsonsprob:: pa-ex-maxdist
   :language: java
   :adaptive:
   :maxdist: 2

   The following program segment is a method that should return string array 
   that is in reverse order -- so {"b", "a", "z"} should return {"z", "a", "b"}.  

   <p>
      But, the blocks have been mixed up and include <b>two extra blocks</b> that 
      are not needed in a correct solution.  
   </p>
   -----
   public static String[] reverse(String[] arr) {
   =====
       String[] result = new String[arr.length];
   =====
       String[] result = arr; #distractor
   =====
       int i = arr.length - 1;
   =====
       int i = arr.length; #distractor
   =====
       for (String element: arr) {
   =====
       for (element: arr) { #distractor
   =====
         result[i--] = element;
   =====
         result[i] = element; #distractor
   =====
       } // end for loop
   =====
       return result;
   =====
   } // end reverse method
        Ex-31-timed: Ex-30-timed: The following program segment is a method that should return string array
that is in reverse order -- so {"b", "a", "z"} should return {"z", "a", "b"}.

But, the blocks have been mixed up and include two extra blocks that are not needed in a correct solution.

public static String[] reverse(String[] arr) { --- String[] result = new String[arr.length]; --- String[] result = arr; #distractor --- int i = arr.length - 1; --- int i = arr.length; #distractor --- for (String element: arr) { --- for (element: arr) { #distractor --- result[i--] = element; --- result[i] = element; #distractor --- } // end for loop --- return result; --- } // end reverse method

This example shows the use of paired distractors.

The problem has already been simplified by not assessing indentation.

.. parsonsprob:: parson-ex-paired

   Reorder the blocks so that this program prints 'Hello world!'.
   -----
   public class HelloWorld
   {
   =====
   public Class HelloWorld
   {                         #paired
   =====
      public static void main(String[] args)
      {
      =====
      public static void main()
      {                         #paired
      =====
         System.out.println("Hello world!");
         =====
         System.out.println("Hello world!") #paired
         =====
      }
      =====
   }
   
        Ex-33-timed: Ex-32-timed: Reorder the blocks so that this program prints 'Hello world!'.public class HelloWorld
{
---
public Class HelloWorld
{                         #paired
---
   public static void main(String[] args)
   {
   ---
   public static void main()
   {                         #paired
   ---
      System.out.println("Hello world!");
      ---
      System.out.println("Hello world!") #paired
      ---
   }
   ---
}
        
Next Section - Poll