\documentclass{article} \input{exer-defs} %\renewcommand{\thepage}{} \newcommand{\app}{\mathbin{\mathtt{@}}} \newcommand{\rev}{\mathtt{rev}} \newcommand{\hd}{\mathtt{hd}} \newcommand{\length}{\mathtt{length}} \newcommand{\cons}{\mathbin{\mathtt{::}}} \newcommand{\xs}{\mathit{xs}} \newcommand{\ys}{\mathit{ys}} \newcommand{\ws}{\mathit{ws}} \newcommand{\zs}{\mathit{zs}} \newcommand{\us}{\mathit{us}} \newcommand{\vs}{\mathit{vs}} \newcommand{\ns}{\mathit{ns}} \newcommand{\ms}{\mathit{ms}} \newcommand{\ls}{\mathit{ls}} \newcommand{\zss}{\mathit{zss}} \newcommand{\myinsert}{\mathtt{insert}} \newcommand{\scanZeroSum}{\mathtt{scanZeroSum}} \newcommand{\extend}{\mathtt{extend}} \newcommand{\bal}{\mathtt{bal}} \newcommand{\balanced}{\mathtt{balanced}} \newcommand{\splitRev}{\mathtt{splitRev}} \newcommand{\None}{\mathtt{None}} \newcommand{\Some}{\mathtt{Some}} \begin{document} \begin{center}\large\bf CIS 705 --- Programming Languages --- Spring 2009 \end{center} \begin{center}\Large\bf Assignment 3 \end{center} \begin{center}\large\bf Model Answers to Exercises 1 and 3 \end{center} \section*{Exercise 1} \renewcommand{\thesection}{1} \theoremnumber{1} \subsection*{Inefficient Version (\texttt{balanced-inefficient.ml})} The ``inefficient'' version of the \texttt{balanced} function uses the function \texttt{sublists} to generate all the sublists of its input, $\mathit{ns}$, listed in strictly ascending order. It then filters-out those sublists that don't satisfy the predicate \texttt{isBalanced}. When called with a list $\mathit{xs}$, \texttt{isBalanced} returns \texttt{false}, if its input is empty or doesn't sum to $0$. Otherwise, it uses \texttt{sublists} to generate all the sublists of $\mathit{xs}$. It then checks that each of these sublists is either empty, has the same length as $\mathit{xs}$ (and so is $\mathit{xs}$), or has a non-$0$ sum. As soon as a nonempty, proper sublist with a sum of $0$ is found, it returns \texttt{false}. The inefficiency of this version of \texttt{balanced} is mainly due to its reliance on generating all the sublists of lists. For example, the list consisting of the first $200$ natural numbers has 20,101 sublists, the list consisting of the first $300$ natural numbers has 45,151, and my attempt at running \texttt{sublists} with the first $1000$ natural numbers resulted in a stack overflow. As a first example, let's consider how \texttt{balanced} works with input $\mathit{ns}=[1;2;3;4;5;-12;3;4;5;-15]$. There are $50$ sublists of this list: \begin{quotation} \raggedright \noindent $[\,]$, $[-15]$, $[-12]$, $[-12; 3]$, $[-12; 3; 4]$, $[-12; 3; 4; 5]$, $[-12; 3; 4; 5; -15]$, $[1]$, $[1; 2]$, $[1; 2; 3]$, $[1; 2; 3; 4]$, $[1; 2; 3; 4; 5]$, $[1; 2; 3; 4; 5; -12]$, $[1; 2; 3; 4; 5; -12; 3]$, $[1; 2; 3; 4; 5; -12; 3; 4]$,\\ $[1; 2; 3; 4; 5; -12; 3; 4; 5]$, $[1; 2; 3; 4; 5; -12; 3; 4; 5; -15]$, $[2]$, $[2; 3]$, $[2; 3; 4]$, $[2; 3; 4; 5]$, $[2; 3; 4; 5; -12]$, $[2; 3; 4; 5; -12; 3]$, $[2; 3; 4; 5; -12; 3; 4]$, $[2; 3; 4; 5; -12; 3; 4; 5]$, \\ $[2; 3; 4; 5; -12; 3; 4; 5; -15]$, $[3]$, $[3; 4]$, $[3; 4; 5]$, $[3; 4; 5; -15]$, $[3; 4; 5; -12]$, $[3; 4; 5; -12; 3]$, $[3; 4; 5; -12; 3; 4]$, $[3; 4; 5; -12; 3; 4; 5]$, $[3; 4; 5; -12; 3; 4; 5; -15]$, $[4]$, $[4; 5]$, $[4; 5; -15]$, $[4; 5; -12]$, $[4; 5; -12; 3]$, $[4; 5; -12; 3; 4]$, $[4; 5; -12; 3; 4; 5]$, $[4; 5; -12; 3; 4; 5; -15]$, $[5]$, $[5; -15]$, $[5; -12]$, $[5; -12; 3]$, $[5; -12; 3; 4]$, $[5; -12; 3; 4; 5]$, $[5; -12; 3; 4; 5; -15]$. \end{quotation} When the predicate \texttt{isBalanced} is called on these $50$ lists, all but the following $5$ are rejected for either being empty or not summing to $0$: \begin{quotation} \noindent $[-12; 3; 4; 5]$, $[1; 2; 3; 4; 5; -12; 3; 4; 5; -15]$, $[3; 4; 5; -12]$, $[4; 5; -12; 3]$, $[5; -12; 3; 4]$. \end{quotation} For each element $\mathit{xs}$ of this list, \texttt{isBalanced} is forced to generate all the sublists of $\mathit{xs}$, verifying that each such sublist $\mathit{ys}$ is either empty, $\mathit{xs}$ or has a non-$0$ sum. All but the second of the five candidates check out, and, of course, the second candidate is $\mathit{ns}$ itself, which has all of the other four sublists as nonempty, proper sublists with sum $0$. Note that the list of all sublists of $\mathit{ns}$ was computed twice: once by \texttt{balanced}, and once by \texttt{isBalanced}. As a second example, let's consider how \texttt{balanced} works with $\mathit{ns}=[1; 2; 3; 0; -3; -2; -1]$. There are $29$ sublists of this list: \begin{quotation} \raggedright \noindent $[\,]$, $[-3]$, $[-3; -2]$, $[-3; -2; -1]$, $[-2]$, $[-2; -1]$, $[-1]$, $[0]$, $[0; -3]$, $[0; -3; -2]$, $[0; -3; -2; -1]$, $[1]$, $[1; 2]$, $[1; 2; 3]$, $[1; 2; 3; 0]$, $[1; 2; 3; 0; -3]$, $[1; 2; 3; 0; -3; -2]$, $[1; 2; 3; 0; -3; -2; -1]$, $[2]$, $[2; 3]$, $[2; 3; 0]$, $[2; 3; 0; -3]$, $[2; 3; 0; -3; -2]$, $[2; 3; 0; -3; -2; -1]$, $[3]$, $[3; 0]$, $[3; 0; -3]$, $[3; 0; -3; -2]$, $[3; 0; -3; -2; -1]$. \end{quotation} When the predicate \texttt{isBalanced} is called on these $29$ lists, all but the following $4$ are rejected for either being empty or not summing to $0$: \begin{quotation} \noindent $[0]$, $[1; 2; 3; 0; -3; -2; -1]$, $[2; 3; 0; -3; -2]$, $[3; 0; -3]$. \end{quotation} For each element $\mathit{xs}$ of this list, \texttt{isBalanced} is forced to generate all the sublists of $\mathit{xs}$, verifying that each such sublist $\mathit{ys}$ is either empty, $\mathit{xs}$ or has a non-$0$ sum. This time, only the first candidate checks out. The sublists of $[0]$---i.e., $[\,]$ and $[0]$---are either empty or $[0]$ itself. All of the other candidates have $[0]$ as a nonempty, proper sublist. \subsection*{Efficient Version (\texttt{balanced.ml})} The ``efficient'' version of the \texttt{balanced} function uses the tail-recursive auxiliary function \texttt{bal} to do its work. \texttt{bal} has three arguments: \begin{itemize} \item $\mathit{ms}$, which is the suffix of the overall input, $\mathit{ns}$, that remains to be processed; \item $\mathit{xs}$, which is the reversal of the longest nice (having no nonempty sublists summing to $0$) suffix of the part of $\mathit{ns}$ that's already been processed; and \item $\mathit{zss}$, which is all the balanced sublists of the part of $\mathit{ns}$ that's already been processed, listed in strictly ascending order. \end{itemize} To begin with, $\mathit{ms}=\mathit{ns}$, $\mathit{xs}=[\,]$ and $\mathit{zss}=[\,]$, and when $\mathit{ms}$ becomes empty, $\mathit{zss}$ is \texttt{balanced}'s answer. When $\mathit{ms}$ is nonempty, the \texttt{extend} function is used to process its next element, $m$. The function \texttt{scanZeroSum} is first used to look for a prefix of $\mathit{xs}$ such that the sum of $m$ and the prefix's sum is $0$. \begin{itemize} \item If there is no such prefix, then \texttt{extend} communicates back to \texttt{bal} that no new balanced sublists of $\mathit{ns}$ have been found, and that the new version of $\mathit{xs}$ will be $m\cons\mathit{xs}$, and then \texttt{bal} iterates, replacing $\mathit{ms}$ with its tail, $\mathit{xs}$ with $m\cons\mathit{xs}$, and leaving $\mathit{zss}$ unchanged. Only one list cell needed to be created in this case, but length of $\mathit{xs}$ additions were needed. All of the processing is done tail-recursively. In the worst case, $\mathit{xs}$ can grow to be as long as $\mathit{ns}$. \item On the other hand, if there is a prefix $\mathit{ys}$ of $xs$ such that $m$ plus the sum of $\mathit{ys}$ is $0$, then \texttt{extend} communicates back to \texttt{bal} that the reversal of $m\cons\mathit{ys}$ is a newly found balanced sublist of $\mathit{ns}$ and that all but the last element of $m\cons\mathit{ys}$ should be the new version of $\mathit{xs}$, and then \texttt{bal} iterates, replacing $\mathit{ms}$ with its tail, $\mathit{xs}$ with all but the last element of $m\cons\mathit{ys}$, and adding the reversal of $m\cons\mathit{ys}$ to $\mathit{zss}$. It takes two times the length of $\mathit{ys}$ plus $2$ list cell allocations to build the new version of $\mathit{xs}$ and find the new element of $\mathit{zss}$. And all of this processing is done tail-recursively, except for the insertion of the new answer into $\mathit{zss}$. If $\mathit{ys}$ is short (when $m=0$, it will be empty), then the new version of $\mathit{xs}$ will also be short, making subsequent steps more efficient. \end{itemize} As a first example (also considered with the inefficient version), let's consider how \texttt{balanced} works with input $\mathit{ns}=[1;2;3;4;5;-12;3;4;5;-15]$. We start out with \begin{displaymath} \mathit{ms}=[1; 2; 3; 4; 5; -12; 3; 4; 5; -15],\qquad \mathit{xs}=[\,],\qquad \mathit{zss}=[\,]. \end{displaymath} The first five steps simply add elements to the front of $\mathit{xs}$. First, $1$ is added, because there is no prefix of $\mathit{xs}$ whose sum plus $1$ is $0$, \begin{displaymath} \mathit{ms}=[2; 3; 4; 5; -12; 3; 4; 5; -15],\qquad \mathit{xs}=[1],\qquad \mathit{zss}=[\,], \end{displaymath} Next $2$ is added, \begin{displaymath} \mathit{ms}=[3; 4; 5; -12; 3; 4; 5; -15],\qquad \mathit{xs}=[2; 1],\qquad \mathit{zss}=[\,]. \end{displaymath} Then $3$ is added, \begin{displaymath} \mathit{ms}=[4; 5; -12; 3; 4; 5; -15],\qquad \mathit{xs}=[3; 2; 1],\qquad \mathit{zss}=[\,]. \end{displaymath} Then $4$ is added, \begin{displaymath} \mathit{ms}=[5; -12; 3; 4; 5; -15],\qquad \mathit{xs}=[4; 3; 2; 1],\qquad \mathit{zss}=[\,]. \end{displaymath} And finally $5$ is added, \begin{displaymath} \mathit{ms}=[-12; 3; 4; 5; -15],\qquad \mathit{xs}=[5; 4; 3; 2; 1],\qquad \mathit{zss}=[\,]. \end{displaymath} Because the next element of $\mathit{ms}$ is now $-12$, and $[5;4;3]$ is a prefix of $\mathit{xs}$ whose sum plus $-12$ is $0$, in the next step, $\mathit{xs}$ becomes all but the last element of $[-12;5;4;3]$, and the reversal of $[-12;5;4;3]$ is inserted into $\mathit{zss}$, \begin{displaymath} \mathit{ms}=[3; 4; 5; -15],\qquad \mathit{xs}=[-12; 5; 4],\qquad \mathit{zss}=[[3; 4; 5; -12]]. \end{displaymath} Because the next element of $\mathit{ms}$ is now $3$, and $[-12;5;4]$ is a prefix of $\mathit{xs}$ whose sum plus $3$ is $0$, in the next step, $\mathit{xs}$ becomes all but the last element of $[3;-12;5;4]$, and the reversal of $[3;-12;5;4]$ is inserted into $\mathit{zss}$, \begin{displaymath} \mathit{ms}=[4; 5; -15],\qquad \mathit{xs}=[3; -12; 5],\qquad \mathit{zss}=[[3; 4; 5; -12]; [4; 5; -12; 3]]. \end{displaymath} Because the next element of $\mathit{ms}$ is now $4$, and $[3;-12;5]$ is a prefix of $\mathit{xs}$ whose sum plus $4$ is $0$, in the next step, $\mathit{xs}$ becomes all but the last element of $[4;3;-12;5]$, and the reversal of $[4;3;-12;5]$ is inserted into $\mathit{zss}$, \begin{displaymath} \mathit{ms}=[5; -15],\qquad \mathit{xs}=[4; 3; -12],\qquad \mathit{zss}=[[3; 4; 5; -12]; [4; 5; -12; 3]; [5; -12; 3; 4]]. \end{displaymath} Because the next element of $\mathit{ms}$ is now $5$, and $[4;3;-12]$ is a prefix of $\mathit{xs}$ whose sum plus $5$ is $0$, in the next step, $\mathit{xs}$ becomes all but the last element of $[5;4;3;-12]$, and the reversal of $[5;4;3;-12]$ is inserted into $\mathit{zss}$, \begin{displaymath} \mathit{ms}=[-15],\qquad \mathit{xs}=[5; 4; 3],\qquad \mathit{zss}=[[-12; 3; 4; 5]; [3; 4; 5; -12]; [4; 5; -12; 3]; [5; -12; 3; 4]]. \end{displaymath} Because the next element of $\mathit{ms}$ is now $-15$, and there is no prefix of $\mathit{xs}$ whose sum plus $-15$ is $0$, in the next step, $-15$ is simply added to the front of $\mathit{xs}$, \begin{displaymath} \mathit{ms}=[\,],\qquad \mathit{xs}=[-15; 5; 4; 3],\qquad \mathit{zss}=[[-12; 3; 4; 5]; [3; 4; 5; -12]; [4; 5; -12; 3]; [5; -12; 3; 4]]. \end{displaymath} Finally, $\mathit{ms}$ is empty, so the result is $\mathit{zss}$. As a second example (also considered with the inefficient version), let's consider how \texttt{balanced} works with input $\mathit{ns}=[1; 2; 3; 0; -3; -2; -1]$. We start out with \begin{displaymath} \mathit{ms}=[1; 2; 3; 0; -3; -2; -1],\qquad \mathit{xs}=[],\qquad \mathit{zss}=[]. \end{displaymath} First, we add $1$ to $\mathit{xs}$, \begin{displaymath} \mathit{ms}=[2; 3; 0; -3; -2; -1],\qquad \mathit{xs}=[1],\qquad \mathit{zss}=[]. \end{displaymath} Next, we add $2$ to $\mathit{xs}$, \begin{displaymath} \mathit{ms}=[3; 0; -3; -2; -1],\qquad \mathit{xs}=[2; 1],\qquad \mathit{zss}=[]. \end{displaymath} Next, we add $3$ to $\mathit{xs}$, \begin{displaymath} \mathit{ms}=[0; -3; -2; -1],\qquad \mathit{xs}=[3; 2; 1],\qquad \mathit{zss}=[]. \end{displaymath} Because the next element of $\mathit{ms}$ is now $0$, and $[\,]$ is a prefix of $\mathit{xs}$ whose sum plus $0$ is $0$, in the next step, $\mathit{xs}$ becomes all but the last element of $[0]$, and the reversal of $[0]$ is inserted into $\mathit{zss}$, \begin{displaymath} \mathit{ms}=[-3; -2; -1],\qquad \mathit{xs}=[],\qquad \mathit{zss}=[[0]]. \end{displaymath} The rest of the steps add $-3$, $-2$ and $-1$ to $\mathit{xs}$, without adding anything to $\mathit{zss}$. \section*{Exercise 3} \renewcommand{\thesection}{3} \theoremnumber{1} \subsection*{Preliminaries} In what follows, we'll abbreviate \texttt{List.rev}, \texttt{List.hd} and \texttt{List.length} to \texttt{rev}, \texttt{hd} and \texttt{length}, respectively. $\length$ is defined so that, for all lists $\xs$ and $\ys$ of values of the same type, $\length(\xs\app\ys)=\length\,\xs + \length\,\ys$. And $\rev$ is defined so that, for all lists $\xs$ and $\ys$ of values of the same type, $\rev(\xs\app\ys) = \rev\,\ys \app \rev\,\xs$. We'll use the following lemma about $\rev$ repeatedly and without citation: \begin{lemma} \label{RevLem} \begin{enumerate}[\quad(1)] \item For all lists $\xs$, $\rev(\rev\,\xs)=\xs$. \item For all lists $\xs$ and $\ys$ of values of the same type, $\xs=\ys$ iff $\rev\,\xs = \rev\,\ys$. \item For all lists $\xs$ and $\ys$ of values of the same type, $\xs = \rev\,ys$ iff $\rev\,\xs = \ys$. \item For all lists $\xs$, $\length\,\xs=\length(\rev\,\xs)$. \end{enumerate} \end{lemma} \begin{proof} (1) can be proved by induction on $\xs$. (2) and (3) follow immediately from (1). And (4) follows by induction on $\xs$. \end{proof} \begin{lemma} \label{SuffixesOfNiceLem} For all nice lists $\xs$ and suffixes $\us$ and $\vs$ of $\xs$, if $\us$ and $\vs$ have the same sum, then $\us=\vs$. \end{lemma} \begin{proof} Suppose $\xs$ is a nice list and $\us$ and $\vs$ are suffixes of $\xs$ with the same sum. We must show that $\us=\vs$. We'll consider the case where $\us$ is no longer than $\vs$, the other case being symmetric. Thus $\vs=\ws\app\us$ for some $\ws$. Since $\ws$ is a sublist of $\vs$, which is a sublist of $\xs$, we have that $\ws$ is a sublist of $\xs$. Since $\us$ and $\vs$ have the same sum, and the sum of $\vs$ is the sum of $\ws$ plus the sum of $\us$, it follows that $\ws$ has a sum of $0$. Thus, because $\xs$ is nice and $\ws$ is a sublist of $\xs$, we have that $\ws=[\,]$, so that $\us = [\,]\app\us = \ws\app\us = \vs$. \end{proof} \begin{lemma} \label{BalancedSuffixLem} There is at most one balanced suffix of a list of integers $\ns$. \end{lemma} \begin{proof} Suppose $\us$ and $\vs$ are balanced suffixes of a list of integers $\ns$. We must show that they are equal. We'll consider the case where $\us$ is no longer than $\vs$, the other case being symmetric. Thus $\vs=\ws\app\us$ for some $\ws$. Because $\us$ and $\vs$ both sum to $0$, the sum of $\ws$ must also be $0$. Thus, since $\ws\app\us=\vs$ is balanced, we have that either $\ws=[\,]$ or $\us=[\,]$, as otherwise both of $\ws$ and $\us$ would be proper, nonempty sublists of $\vs$ with sum $0$. In the first case, we have that $\us = [\,]\app\us = \ws\app\us = \vs$. And, in the second case, we have that $[\,]=\us$ is balanced---contradiction. Thus $\us=\vs$. \end{proof} \begin{lemma} \label{NicePlusNonZeroImpliesBalancedLem} If $\xs$ is a nice list, $n$ is a nonzero integer, and the sum of $\xs$ plus $n$ is $0$, then $\xs\app[n]$ is balanced. \end{lemma} \begin{proof} Suppose $\xs$ is a nice list, $n$ is a nonzero integer, and the sum of $\xs$ plus $n$ is $0$. We must show that $\xs\app[n]$ is balanced. Because it clearly has a sum of $0$ and is nonempty, it remains to show that it has no proper, nonempty sublist with sum $0$. Suppose, toward a contradiction, that $\us$ is a proper, nonempty sublist of $\xs\app[n]$ with sum $0$. There are two cases to consider. \begin{itemize} \item Suppose $\us$ is a sublist of $\xs$. Because $\us$ is nonempty and sums to $0$, and $\xs$ is nice, we have a contradiction. \item Suppose $\us$ is a suffix of $\xs\app[n]$. Because $\us$ is nonempty, there is a suffix $\vs$ of $\xs$ such that $\us=\vs\app[n]$. Because $\us$ sums to $0$, it follows that $\vs$ sums to $-n$. But the sum of $\xs$ plus $n$ is $0$, and thus $\xs$ also sums to $-n$. Because $\xs$ and $\vs$ are suffixes of the same nice list ($\xs$) and have the same sum, Lemma~\ref{SuffixesOfNiceLem} tells us that $\xs=\vs$. But then $\us=\vs\app[n]=\xs\app[n]$, contradicting that $\us$ is a proper sublist of $\xs\app[n]$. \end{itemize} \end{proof} \begin{lemma} \label{NiceCharactLem} Suppose $\ns$ and $\xs$ are lists of integers. The following statements are equivalent: \begin{enumerate}[\quad(1)] \item the reversals of the prefixes of $\xs$ are the nice suffixes of $\ns$; \item $\rev\,\xs$ is the longest nice suffix of $\ns$. \end{enumerate} \end{lemma} \begin{proof} Suppose that $\ns$ and $\xs$ are lists of integers. \begin{itemize} \item ((1) implies (2))\quad Suppose the reversals of the prefixes of $\xs$ are the nice suffixes of $\ns$. We must show that $\rev\,\xs$ is the longest nice suffix of $\ns$. Because $\xs$ is a prefix of itself, $\rev\,\xs$ is a nice suffix of $\ns$. Suppose, toward a contradiction, that there is nice suffix $\ms$ of $\ns$ that is longer than $\rev\,\xs$. Then $\ms=\rev\,\ys$ for some prefix $\ys$ of $\xs$. Because $\rev\,\ys=\ms$ is longer than $\rev\,\xs$, we have that $\ys=\rev(\rev\,\ys)$ is longer than $\xs=\rev(\rev\,\xs)$---contradicting the fact that $\ys$ is a prefix of $\xs$. Thus $\rev\,\xs$ is the longest nice suffix of $\ns$. \item ((2) implies (1))\quad Suppose $\rev\,\xs$ is the longest nice suffix of $\ns$. We must show that the reversals of the prefixes of $\xs$ are the nice suffixes of $\ns$. First, suppose that $\ys$ is a prefix of $\xs$. Then $\xs=\ys\app\us$ for some $\us$, so that $\rev\,\us\app\rev\,\ys=\rev(\ys\app\us)=\rev\,\xs$. Because $\rev\,\ys$ is a suffix of $\rev\,\xs$, which is in turn a suffix of $\ns$, we have that $\rev\,\ys$ is a suffix of $\ns$. And since $\rev\,\ys$ is a sublist of the nice list $\rev\,\xs$, it follows that $\rev\,\ys$ is nice, as any nonempty sublist of $\rev\,\ys$ with a sum of $0$ would also be a nonempty sublist of $\rev\,\xs$. Thus $\rev\,\ys$ is a nice suffix of $\ns$. Second, suppose that $\ms$ is a nice suffix of $\ns$. Because $\rev\,\xs$ is the longest nice suffix of $\ns$, it follows that $\ms$ is a suffix of $\rev\,\xs$. Thus there is a $\us$ such that $\rev\,\xs = \us\app\ms$, so that $\xs = \rev(\rev\,\xs) = \rev(\us\app\ms) = \rev\,\ms\app\rev\,\us$. Hence $\rev\,\ms$ is a prefix of $\xs$ whose reversal is $\ms$. \end{itemize} \end{proof} \subsection*{Correctness Proof for \texttt{extend}} Suppose $\ns$ is a list of integers, $n$ is an integer, and the reversals of the prefixes of $\xs$ are the nice suffixes of $\ns$. By Lemma~\ref{NiceCharactLem}, we have that $\rev\,\xs$ is the longest nice suffix of $\ns$. There are two cases to consider. \begin{itemize} \item Suppose there is no prefix of $\xs$ whose sum, when added to $n$, yields $0$. Then $\scanZeroSum\,n\,\xs$ returns $\None$, so that $\extend\,n\,\xs$ returns $(\None, n\cons\xs)$. Thus we must show that: \begin{enumerate}[\quad(1)] \item there is no balanced suffix of $\ns\app[n]$, and \item the reversals of the prefixes of $n\cons\xs$ are the nice suffixes of $\ns\app[n]$, which, by Lemma~\ref{NiceCharactLem}, is equivalent to showing that $\rev\,xs\app[n]=\rev(n\cons\xs)$ is the longest nice suffix of $\ns\app[n]$. \end{enumerate} We have that $n\neq 0$, since otherwise $[\,]$ would be a prefix of $\xs$ whose sum, when added to $n$, yields $0$. Suppose, toward a contradiction, that there is a balanced suffix of $\ns\app[n]$. Because balanced lists are nonempty, it follows that there is a suffix $\ms$ of $\ns$ such that $\ms\app[n]$ is balanced. Because $\ms$ is a proper sublist of $\ms\app[n]$, it follows that $\ms$ is nice (a nonempty sublist of $\ms$ with sum $0$ would be a proper, nonempty sublist of $\ms\app[n]$). Thus, since $\ms$ is a nice suffix of $\ns$, we have that $\rev\,\ms$ is a prefix of $\xs$. Because $\ms\app[n]$ is balanced, we have that the sum of $\ms$, when added to $n$, yields $0$. But then the sum of $\rev\,\ms$, when added to $n$, also yields $0$, so that there is prefix of $\xs$ whose sum, when added to $n$, yields $0$---contradiction. Thus there is no balanced suffix of $\ns\app[n]$, i.e., (1) holds. It remains to show (2). Suppose, toward a contradiction, that $\rev\,\xs\app[n]$ is not nice. Because $n\neq 0$ and $\rev\,\xs$ is nice, it follows that there is a nonempty suffix $\us$ of $\rev\,\xs$ such that the sum of $\us$, when added to $n$, yields $0$. Because $\us$ is a sublist of $\rev\,\xs$, and $\rev\,\xs$ is nice, we have that $\us$ is nice. Thus Lemma~\ref{NicePlusNonZeroImpliesBalancedLem} tells us that $\us\app[n]$ is balanced. Since $\us$ is a suffix of $\rev\,\xs$, and $\rev\,xs$ is a suffix of $\ns$, we have that $\us$ is a suffix of $\ns$, so that $\us\app[n]$ is a balanced suffix of $\ns\app[n]$---contradiction. Thus we have that $\rev\,\xs\app[n]$ is a nice suffix of $\ns\app[n]$. Finally, suppose, toward a contradiction, that there is a nice suffix $\us$ of $\ns\app[n]$ that is longer than $\rev\,\xs\app[n]$. Then $\us=\ms\app[n]$, where $\ms$ is a longer suffix of $\ns$ than $\rev\,xs$. Because $\us$ is nice and $\ms$ is a sublist of $\us$, we have that $\ms$ is nice, so that $\ms$ is a nice suffix of $\ns$ that is longer than $\rev\,xs$---contradiction. This concludes the proof of (2). \item Suppose there is a prefix of $\xs$ whose sum, when added to $n$, yields $0$. Let $\ys$ be the shortest such prefix. Then $\scanZeroSum\,n\,\xs$ returns $\Some\,i$, where $i$ is the length of $\ys$. Since $0\leq i$ and $i$ is less-than-or-equal-to the length of $n\cons\xs$, $\splitRev\,i\,(n\cons\xs)$ returns $(\us,\vs)$, where $\us$ is the reversal of the first $i$ elements of $n\cons\xs$, and $\vs$ is the remaining elements of $n\cons\xs$. Thus $\extend\,n\,\xs$ returns $(\Some(\hd\,\vs\cons\us), \rev\,\us)$. Because $i$ is the length of $\ys$, and $\ys$ is a prefix of $\xs$, it follows that $\rev\,\us$ is all but the last element of $n\cons\ys$, and that $\hd\,\vs$ is the last element of $n\cons\ys$. Thus $n\cons\ys = \rev\,\us\app[\hd\,\vs]$. Hence $\rev(n\cons\ys) = \rev(\rev\,\us\app[\hd\,\vs]) = \rev[\hd\,\vs]\app\rev(\rev\,\us) = [\hd\,\vs]\app\us = \hd\,\vs\cons\us$. Thus $\extend\,n\,\xs$ returns $\Some(\rev(n\cons\ys))$ paired with all but the last element of $n\cons\ys$. Hence we must show that: \begin{enumerate}[\quad(1)] \item $\rev(n\cons\ys)$ is the unique balanced suffix of $\ns\app[n]$, which, by Lemma~\ref{BalancedSuffixLem}, is equivalent to showing that $\rev\,\ys\app[n]=\rev(n\cons\ys)$ is a balanced suffix of $\ns\app[n]$, and \item the reversals of the prefixes of all but the last element of $n\cons\ys$ are the nice suffixes of $\ns\app[n]$, which, by Lemma~\ref{NiceCharactLem}, is equivalent to showing that the reversal of all but the last element of $n\cons\ys$ is the longest nice suffix of $\ns\app[n]$. \end{enumerate} We know that $n$ plus the sum of $\ys$ is $0$, and thus that $\rev\,\ys\app[n]$ has a sum of $0$. And, clearly $\rev\,\ys\app[n]$ is nonempty. So for (1) it remains to show that $\rev\,\ys\app[n]$ has no proper, nonempty sublist with a sum of $0$. To this end, suppose, toward a contradiction, that $\zs$ is a proper, nonempty sublist of $\rev\,\ys\app[n]$ with a sum of $0$. Because $\ys$ is a prefix of $\xs$, $\rev\,\ys$ is a nice suffix of $\ns$. Thus $\zs$ is not a sublist of $\rev\,\ys$, so that $\zs=\ws\app[n]$ for some suffix $\ws$ of $\rev\,\ys$. Since the sum of $\zs$ is $0$, we have that the sum of $\ws$ is $-n$. But, since the sum of $\rev\,\ys\app[n]$ is $0$, we also have that the sum of $\rev\,\ys$ is $-n$. Because $\rev\,\ys$ is nice, $\rev\,\ys$ and $\ws$ are suffixes of $\rev\,\ys$, and $\rev\,\ys$ and $\ws$ have identical sums, Lemma~\ref{SuffixesOfNiceLem} tells us that $\rev\,\ys=\ws$. But this means that $\zs=\ws\app[n]=\rev\,\ys\app[n]$, showing that $\zs$ is not a proper sublist of $\rev\,\ys\app[n]$---contradiction. This completes the proof of (1). For (2), there are two cases to consider. \begin{itemize} \item Suppose $n=0$. Then $\ys=[\,]$, by its definition. Hence all but the last element of $n\cons\ys$ is $[\,]$. So we must show that $[\,] = \rev[\,]$ is the longest nice suffix of $\ns\app[n]$. $[\,]$ is nice and is a suffix of any list. Furthermore, any longer suffix of $\ns\app[n]$ would have $[0]$ as a sublist, and so wouldn't be nice. So $[\,]$ is the longest nice suffix of $\ns\app[n]$. \item Suppose $n\neq 0$. Then the sum of $\ys$ is $-n$, so that $\ys=\us\app[m]$ for some $\us$ and $m$. We must show that $\rev\,\us\app[n]=\rev(n\cons\us)$ is the longest nice suffix of $\ns\app[n]$. We have that $\rev\,\ys\app[n] = \rev(\us\app[m])\app[n] = m\cons\rev\,\us\app[n]$. From (1), we know that $\rev\,\ys\app[n]$ is a balanced suffix of $\ns\app[n]$. Since $\rev\,\us\app[n]$ is a suffix of $\rev\,\ys\app[n]$, we have that $\rev\,\us\app[n]$ is a suffix of $\ns\app[n]$. Furthermore, because $\rev\,\us\app[n]$ is a proper sublist of the balanced list $\rev\,\ys\app[n]$, it follows that $\rev\,\us\app[n]$ is nice (if $\rev\,\us\app[n]$ had a nonempty sublist with sum $0$, then $\rev\,\ys\app[n]$ would have a proper, nonempty sublist with sum $0$). Furthermore, any longer suffix of $\ns\app[n]$ would contain $m\cons\rev\,\us\app[n] = \rev\,\ys\app[n]$ (which has a sum of $0$) as a sublist, and so wouldn't be nice. Thus $\rev\,\us\app[n]$ is the longest nice suffix of $\ns\app[n]$. \end{itemize} \end{itemize} \subsection*{Correctness Proof for \texttt{balanced}} Suppose $\ns$ is a list of integers. First, we'll show that, under the assumption that the auxiliary function $\bal$ is correct, $\balanced\;\ns$ returns the balanced sublists of $\ns$, listed in strictly ascending order. Then, we'll prove that $\bal$ is correct. We have that $\ns$ is a suffix of itself, and the prefix of $\ns$ of length $\length\,\ns - \length\,\ns$ is $[\,]$. Since the reversals of the prefixes of $[\,]$ (there is only one, $[\,]$) are the nice suffixes of $[\,]$ (there is only one, $[\,]$), we have that the reversals of the prefixes of $[\,]$ are the nice suffixes of the prefix of $\ns$ of length $\length\,\ns - \length\,\ns$. Since there are no balanced sublists of $[\,]$, we have that $[\,]$ is the balanced sublists of $[\,]$, listed in strictly ascending order, i.e., is the balanced sublists of the prefix of $\ns$ of length $\length\,\ns - \length\,\ns$, listed in strictly ascending order. Thus, by $\bal$'s specification, $\bal\,\ns\,[\,]\,[\,]$ returns the balanced sublists of $\ns$, listed in strictly ascending order. And this, in turn, is what $\balanced\,\ns$ returns. To prove that $\bal$ is correct, suppose $\ms$ is a suffix of $\ns$, and the reversals of the prefixes of $\xs$ are the nice suffixes of the prefix of $\ns$ of length $\length\,\ns-\length\,\ms$, and $\zss$ is the balanced sublists of the prefix of $\ns$ of length $\length\,\ns-\length\,\ms$, listed in strictly ascending order. We must prove that $\bal\,\ms\,\xs\,\zss$ returns all the balanced sublists of $\ns$, listed in strictly ascending order. There are two cases to consider. \begin{itemize} \item Suppose $\ms=[\,]$. Then the prefix of $\ns$ of length $\length\,\ns-\length\,\ms$ is $\ns$, and so $\zss$ is the balanced sublists of $\ns$, listed in strictly ascending order. But this is what $\bal$ returns. \item Suppose $\ms=m\cons\ms'$ for some integer $m$ and list of integers $\ms'$. Because $\ms$ is a suffix of $\ns$, we have that $\ms'$ is a suffix of $\ns$. Let $\ls$ be the prefix of $\ns$ of length $\length\,\ns-\length\,\ms$. Then $\ls\app[m]$ is the prefix of $\ns$ of length $\length\,\ns-\length\,\ms'$. There are two subcases to consider. \begin{itemize} \item Suppose there is no balanced suffix of $\ls\app[m]$. Because the reversals of the prefixes of $\xs$ are the nice suffixes of $\ls$, we have that $\extend\,m\,\xs$ returns $(\None,\ys)$, where the reversals of the prefixes of $\ys$ are the nice suffixes of $\ls\app[m]$. Because $\zss$ is the balanced sublists of $\ls$, listed in strictly ascending order, and there is no balanced suffix of $\ls\app[m]$, we have that $\zss$ is the balanced sublists of $\ls\app[m]$, listed in strictly ascending order. Thus, by the specification of $\bal$, we have that $\bal\,\ms'\,\ys\,\zss$ returns the balanced sublists of $\ns$, listed in strictly ascending order. But this is what $\bal$ returns. \item Suppose there is a balanced suffix of $\ls\app[m]$. Because the reversals of the prefixes of $\xs$ are the nice suffixes of $\ls$, we have that $\extend\,m\,\xs$ returns $(\Some\,zs,\ys)$, where $\zs$ is the unique balanced suffix of $\ls\app[m]$, and the reversals of the prefixes of $\ys$ are the nice suffixes of $\ls\app[m]$. Since the elements of $\zss$ are sorted in strictly ascending order, $\myinsert\,\zs\,\zss$ consists of $\zs$ plus all of the elements in $\zss$, listed in strictly ascending order. Because $\zss$ is the balanced sublists of $\ls$, and $\zs$ is the unique balanced suffix of $\ls\app[m]$, it follows that $\myinsert\,\zs\,\zss$ is the balanced sublists of $\ls\app[m]$, listed in strictly ascending order. Thus, by the specification of $\bal$, we have that $\bal\,\ms'\,\ys\,(\myinsert\,\zs\,\zss)$ returns the balanced sublists of $\ns$, listed in strictly ascending order. But this is what $\bal$ returns. \end{itemize} \end{itemize} \end{document}