# HG changeset patch # User Christian Urban # Date 1604162866 0 # Node ID 40657f9a4e4a9a483849a07908580b8f6586563b # Parent a2ac7e3fa3301541e8fc1dbad185cd7343af2c86 updated diff -r a2ac7e3fa330 -r 40657f9a4e4a cws/main_cw01.tex --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cws/main_cw01.tex Sat Oct 31 16:47:46 2020 +0000 @@ -0,0 +1,237 @@ +% !TEX program = xelatex +\documentclass{article} +\usepackage{../style} +\usepackage{disclaimer} +\usepackage{../langs} + + + +\begin{document} + +\section*{Core Part 6 (Scala, 7 Marks)} + +\IMPORTANT{This part is about Scala. It is due on \cwSIXa{} at 5pm and worth 7\%.} + +\noindent +Also note that the running time of each part will be restricted to a +maximum of 30 seconds on my laptop. + +\DISCLAIMER{} + +\subsection*{Reference Implementation} + +Like the C++ assignments, the Scala assignments will work like this: you +push your files to GitHub and receive (after sometimes a long delay) some +automated feedback. In the end we take a snapshot of the submitted files and +apply an automated marking script to them.\medskip + +\noindent +In addition, the Scala coursework comes with a reference implementation +in form of \texttt{jar}-files. This allows you to run any test cases +on your own computer. For example you can call Scala on the command +line with the option \texttt{-cp drumb.jar} and then query any +function from the template file. Say you want to find out what +the function \code{get_january_data} +produces: for this you just need to prefix them with the object name +\texttt{CW6b} and call them with some arguments: + +\begin{lstlisting}[language={},numbers=none,basicstyle=\ttfamily\small] +$ scala -cp drumb.jar + +scala> CW6b.get_january_data("FB", 2014) +val res2: List[String] = List(2014-01-02,54.709999,....) +\end{lstlisting}%$ + +\subsection*{Hints} + +\noindent +\textbf{For the Core Part:} useful string functions: +\texttt{.startsWith(...)} for checking whether a string has a given +prefix, \texttt{\_ ++ \_} for concatenating two strings; useful option +functions: \texttt{.flatten} flattens a list of options such that it +filters way all \texttt{None}'s, \texttt{Try(...).getOrElse ...} runs +some code that might raise an exception---if yes, then a default value +can be given; useful list functions: \texttt{.head} for obtaining the +first element in a non-empty list, \texttt{.length} for the length of +a list; \texttt{.filter(...)} for filtering out elements in a list; +\texttt{.getLines.toList} for obtaining a list of lines from a file; +\texttt{.split(",").toList} for splitting strings according to a +comma.\bigskip + +\noindent +\textbf{Note!} Fortunately Scala supports operator overloading. But +make sure you understand the difference between \texttt{100 / 3} and +\texttt{100.0 / 3}! + +\newpage +\subsection*{Core Part (7 Marks, file drumb.scala)} + +A purely fictional character named Mr T.~Drumb inherited in 1978 +approximately 200 Million Dollar from his father. Mr Drumb prides +himself to be a brilliant business man because nowadays it is +estimated he is 3 Billion Dollar worth (one is not sure, of course, +because Mr Drumb refuses to make his tax records public). + +Since the question about Mr Drumb's business acumen remains open, +let's do a quick back-of-the-envelope calculation in Scala whether his +claim has any merit. Let's suppose we are given \$100 in 1978 and we +follow a really dumb investment strategy, namely: + +\begin{itemize} +\item We blindly choose a portfolio of stocks, say some Blue-Chip stocks + or some Real Estate stocks. +\item If some of the stocks in our portfolio are traded in January of + a year, we invest our money in equal amounts in each of these + stocks. For example if we have \$100 and there are four stocks that + are traded in our portfolio, we buy \$25 worth of stocks + from each. (Be careful to also test cases where you trade with 3 stocks.) +\item Next year in January, we look at how our stocks did, liquidate + everything, and re-invest our (hopefully) increased money in again + the stocks from our portfolio (there might be more stocks available, + if companies from our portfolio got listed in that year, or less if + some companies went bust or were de-listed). +\item We do this for 41 years until January 2019 and check what would + have become out of our \$100. +\end{itemize} + +\noindent +Until Yahoo was bought by Altaba a few years ago, historical stock market +data for such back-of-the-envelope calculations was freely available +online. Unfortunately nowadays this kind of data is more difficult to +obtain, unless you are prepared to pay extortionate prices or be +severely rate-limited. Therefore this part comes with a number +of files containing CSV-lists with the historical stock prices for the +companies in our portfolios. Use these files for the following +tasks.\bigskip + +\newpage +\noindent +\textbf{Tasks} + +\begin{itemize} +\item[(1)] Write a function \texttt{get\_january\_data} that takes a + stock symbol and a year as arguments. The function reads the + corresponding CSV-file and returns the list of strings that start + with the given year (each line in the CSV-list is of the form + \texttt{someyear-01-someday,someprice}).\hfill[1 Mark] + +\item[(2)] Write a function \texttt{get\_first\_price} that takes + again a stock symbol and a year as arguments. It should return the + first January price for the stock symbol in the given year. For this + it uses the list of strings generated by + \texttt{get\_january\_data}. A problem is that normally a stock + exchange is not open on 1st of January, but depending on the day of + the week on a later day (maybe 3rd or 4th). The easiest way to solve + this problem is to obtain the whole January data for a stock symbol + and then select the earliest, or first, entry in this list. The + stock price of this entry should be converted into a double. Such a + price might not exist, in case the company does not exist in the given + year. For example, if you query for Google in January of 1980, then + clearly Google did not exist yet. Therefore you are asked to + return a trade price with type \texttt{Option[Double]}\ldots\texttt{None} + will be the value for when no price exists; \texttt{Some} if there is a + price.\hfill[1 Mark] + +\item[(3)] Write a function \texttt{get\_prices} that takes a + portfolio (a list of stock symbols), a years range and gets all the + first trading prices for each year in the range. You should organise + this as a list of lists of \texttt{Option[Double]}'s. The inner + lists are for all stock symbols from the portfolio and the outer + list for the years. For example for Google and Apple in years 2010 + (first line), 2011 (second line) and 2012 (third line) you obtain: + +\begin{verbatim} + List(List(Some(312.204773), Some(26.782711)), + List(Some(301.0466), Some(41.244694)), + List(Some(331.462585), Some(51.464207)))) +\end{verbatim}\hfill[1 Mark] + + +%\end{itemize} + +%\subsection*{Advanced Part 3 (4 Marks, continue in file drumb.scala)} +% +%\noindent +%\textbf{Tasks} + +%\begin{itemize} + +\item[(4)] Write a function that calculates the \emph{change factor} (delta) + for how a stock price has changed from one year to the next. This is + only well-defined, if the corresponding company has been traded in both + years. In this case you can calculate + + \[ + \frac{price_{new} - price_{old}}{price_{old}} + \] + + If the change factor is defined, you should return it + as \texttt{Some(change\_factor)}; if not, you should return + \texttt{None}.\mbox{}\hfill\mbox{[1 Mark]} + +\item[(5)] Write a function that calculates all change factors + (deltas) for the prices we obtained in Task (2). For the running + example of Google and Apple for the years 2010 to 2012 you should + obtain 4 change factors: + +\begin{verbatim} + List(List(Some(-0.03573991804411003), Some(0.539974575389325)), + List(Some(0.10103414222249969), Some(0.24777764141006836))) +\end{verbatim} + + That means Google did a bit badly in 2010, while Apple did very well. + Both did OK in 2011. Make sure you handle the cases where a company is + not listed in a year. In such cases the change factor should be \texttt{None} + (recall Task~(4)). + \mbox{}\hfill\mbox{[1 Mark]} + +\item[(6)] Write a function that calculates the ``yield'', or + balance, for one year for our portfolio. This function takes the + change factors, the starting balance and the year as arguments. If + no company from our portfolio existed in that year, the balance is + unchanged. Otherwise we invest in each existing company an equal + amount of our balance. Using the change factors computed under Task + (2), calculate the new balance. Say we had \$100 in 2010, we would have + received in our running example involving Google and Apple: + + \begin{verbatim} + $50 * -0.03573991804411003 + $50 * 0.539974575389325 + = $25.21173286726075 + \end{verbatim} + + as profit for that year, and our new balance for 2011 is \$125 when + converted to a \texttt{Long}.\mbox{}\hfill\mbox{[1 Mark]} + +\item[(7)] Write a function that calculates the overall balance + for a range of years where each year the yearly profit is compounded to + the new balances and then re-invested into our portfolio. + For this use the function and results generated under (6).\\ + \mbox{}\hfill\mbox{[1 Mark]} +\end{itemize}\medskip + + + +\noindent +\textbf{Test Data:} File \texttt{drumb.scala} contains two portfolios +collected from the S\&P 500, one for blue-chip companies, including +Facebook, Amazon and Baidu; and another for listed real-estate +companies, whose names I have never heard of. Following the dumb +investment strategy from 1978 until 2019 would have turned a starting +balance of \$100 into roughly \$39,162 for real estate and a whopping +\$462,199 for blue chips. Note when comparing these results with your +own calculations: there might be some small rounding errors, which +when compounded lead to moderately different values.\bigskip + + +\noindent +\textbf{Moral:} Reflecting on our assumptions, we are over-estimating +our yield in many ways: first, who can know in 1978 about what will +turn out to be a blue chip company. Also, since the portfolios are +chosen from the current S\&P 500, they do not include the myriad +of companies that went bust or were de-listed over the years. +So where does this leave our fictional character Mr T.~Drumb? Well, given +his inheritance, a really dumb investment strategy would have done +equally well, if not much better.\medskip + +\end{document} + diff -r a2ac7e3fa330 -r 40657f9a4e4a cws/pcw01.tex --- a/cws/pcw01.tex Sat Oct 31 16:23:12 2020 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,241 +0,0 @@ -% !TEX program = xelatex -\documentclass{article} -\usepackage{../style} -\usepackage{disclaimer} -\usepackage{../langs} - - - -\begin{document} - -\section*{Core Part 6 (Scala, 7 Marks)} - -\IMPORTANT{This part is about Scala. It is due on \cwSIXa{} at 4pm and worth 7\%.} - -\noindent -Also note that the running time of each part will be restricted to a -maximum of 30 seconds on my laptop. - -\DISCLAIMER{} - -\subsection*{Reference Implementation} - -Like the C++ assignments, the Scala assignments will work like this: you -push your files to GitHub and receive (after sometimes a long delay) some -automated feedback. In the end we take a snapshot of the submitted files and -apply an automated marking script to them.\medskip - -\noindent -In addition, the Scala coursework comes with a reference implementation -in form of \texttt{jar}-files. This allows you to run any test cases -on your own computer. For example you can call Scala on the command -line with the option \texttt{-cp drumb.jar} and then query any -function from the template file. Say you want to find out what -the functions ??? -produce: for this you just need to prefix them with the object name -\texttt{CW6b}. -If you want to find out what these functions produce for the argument -\texttt{6}, you would type something like: - -\begin{lstlisting}[language={},numbers=none,basicstyle=\ttfamily\small] -$ scala -cp collatz.jar - -scala> CW6a.collatz(6) -... -scala> CW6a.collatz_max(6) -... -\end{lstlisting}%$ - -\subsection*{Hints} - -\noindent -\textbf{For Core Part:} useful string functions: -\texttt{.startsWith(...)} for checking whether a string has a given -prefix, \texttt{\_ ++ \_} for concatenating two strings; useful option -functions: \texttt{.flatten} flattens a list of options such that it -filters way all \texttt{None}'s, \texttt{Try(...).getOrElse ...} runs -some code that might raise an exception---if yes, then a default value -can be given; useful list functions: \texttt{.head} for obtaining the -first element in a non-empty list, \texttt{.length} for the length of -a list; \texttt{.filter(...)} for filtering out elements in a list; -\texttt{.getLines.toList} for obtaining a list of lines from a file; -\texttt{.split(",").toList} for splitting strings according to a -comma.\bigskip - -\noindent -\textbf{Note!} Fortunately Scala supports operator overloading. But -make sure you understand the difference between \texttt{100 / 3} and -\texttt{100.0 / 3}! - -\newpage -\subsection*{Core Part (7 Marks, file drumb.scala)} - -A purely fictional character named Mr T.~Drumb inherited in 1978 -approximately 200 Million Dollar from his father. Mr Drumb prides -himself to be a brilliant business man because nowadays it is -estimated he is 3 Billion Dollar worth (one is not sure, of course, -because Mr Drumb refuses to make his tax records public). - -Since the question about Mr Drumb's business acumen remains open, -let's do a quick back-of-the-envelope calculation in Scala whether his -claim has any merit. Let's suppose we are given \$100 in 1978 and we -follow a really dumb investment strategy, namely: - -\begin{itemize} -\item We blindly choose a portfolio of stocks, say some Blue-Chip stocks - or some Real Estate stocks. -\item If some of the stocks in our portfolio are traded in January of - a year, we invest our money in equal amounts in each of these - stocks. For example if we have \$100 and there are four stocks that - are traded in our portfolio, we buy \$25 worth of stocks - from each. (Be careful to also test cases where you trade with 3 stocks.) -\item Next year in January, we look at how our stocks did, liquidate - everything, and re-invest our (hopefully) increased money in again - the stocks from our portfolio (there might be more stocks available, - if companies from our portfolio got listed in that year, or less if - some companies went bust or were de-listed). -\item We do this for 41 years until January 2019 and check what would - have become out of our \$100. -\end{itemize} - -\noindent -Until Yahoo was bought by Altaba a few years ago, historical stock market -data for such back-of-the-envelope calculations was freely available -online. Unfortunately nowadays this kind of data is more difficult to -obtain, unless you are prepared to pay extortionate prices or be -severely rate-limited. Therefore this part comes with a number -of files containing CSV-lists with the historical stock prices for the -companies in our portfolios. Use these files for the following -tasks.\bigskip - -\newpage -\noindent -\textbf{Tasks} - -\begin{itemize} -\item[(1)] Write a function \texttt{get\_january\_data} that takes a - stock symbol and a year as arguments. The function reads the - corresponding CSV-file and returns the list of strings that start - with the given year (each line in the CSV-list is of the form - \texttt{someyear-01-someday,someprice}).\hfill[1 Mark] - -\item[(2)] Write a function \texttt{get\_first\_price} that takes - again a stock symbol and a year as arguments. It should return the - first January price for the stock symbol in the given year. For this - it uses the list of strings generated by - \texttt{get\_january\_data}. A problem is that normally a stock - exchange is not open on 1st of January, but depending on the day of - the week on a later day (maybe 3rd or 4th). The easiest way to solve - this problem is to obtain the whole January data for a stock symbol - and then select the earliest, or first, entry in this list. The - stock price of this entry should be converted into a double. Such a - price might not exist, in case the company does not exist in the given - year. For example, if you query for Google in January of 1980, then - clearly Google did not exist yet. Therefore you are asked to - return a trade price with type \texttt{Option[Double]}\ldots\texttt{None} - will be the value for when no price exists; \texttt{Some} if there is a - price.\hfill[1 Mark] - -\item[(3)] Write a function \texttt{get\_prices} that takes a - portfolio (a list of stock symbols), a years range and gets all the - first trading prices for each year in the range. You should organise - this as a list of lists of \texttt{Option[Double]}'s. The inner - lists are for all stock symbols from the portfolio and the outer - list for the years. For example for Google and Apple in years 2010 - (first line), 2011 (second line) and 2012 (third line) you obtain: - -\begin{verbatim} - List(List(Some(312.204773), Some(26.782711)), - List(Some(301.0466), Some(41.244694)), - List(Some(331.462585), Some(51.464207)))) -\end{verbatim}\hfill[1 Mark] - - -%\end{itemize} - -%\subsection*{Advanced Part 3 (4 Marks, continue in file drumb.scala)} -% -%\noindent -%\textbf{Tasks} - -%\begin{itemize} - -\item[(4)] Write a function that calculates the \emph{change factor} (delta) - for how a stock price has changed from one year to the next. This is - only well-defined, if the corresponding company has been traded in both - years. In this case you can calculate - - \[ - \frac{price_{new} - price_{old}}{price_{old}} - \] - - If the change factor is defined, you should return it - as \texttt{Some(change\_factor)}; if not, you should return - \texttt{None}.\mbox{}\hfill\mbox{[1 Mark]} - -\item[(5)] Write a function that calculates all change factors - (deltas) for the prices we obtained in Task (2). For the running - example of Google and Apple for the years 2010 to 2012 you should - obtain 4 change factors: - -\begin{verbatim} - List(List(Some(-0.03573991804411003), Some(0.539974575389325)), - List(Some(0.10103414222249969), Some(0.24777764141006836))) -\end{verbatim} - - That means Google did a bit badly in 2010, while Apple did very well. - Both did OK in 2011. Make sure you handle the cases where a company is - not listed in a year. In such cases the change factor should be \texttt{None} - (recall Task~(4)). - \mbox{}\hfill\mbox{[1 Mark]} - -\item[(6)] Write a function that calculates the ``yield'', or - balance, for one year for our portfolio. This function takes the - change factors, the starting balance and the year as arguments. If - no company from our portfolio existed in that year, the balance is - unchanged. Otherwise we invest in each existing company an equal - amount of our balance. Using the change factors computed under Task - (2), calculate the new balance. Say we had \$100 in 2010, we would have - received in our running example involving Google and Apple: - - \begin{verbatim} - $50 * -0.03573991804411003 + $50 * 0.539974575389325 - = $25.21173286726075 - \end{verbatim} - - as profit for that year, and our new balance for 2011 is \$125 when - converted to a \texttt{Long}.\mbox{}\hfill\mbox{[1 Mark]} - -\item[(7)] Write a function that calculates the overall balance - for a range of years where each year the yearly profit is compounded to - the new balances and then re-invested into our portfolio. - For this use the function and results generated under (6).\\ - \mbox{}\hfill\mbox{[1 Mark]} -\end{itemize}\medskip - - - -\noindent -\textbf{Test Data:} File \texttt{drumb.scala} contains two portfolios -collected from the S\&P 500, one for blue-chip companies, including -Facebook, Amazon and Baidu; and another for listed real-estate -companies, whose names I have never heard of. Following the dumb -investment strategy from 1978 until 2019 would have turned a starting -balance of \$100 into roughly \$39,162 for real estate and a whopping -\$462,199 for blue chips. Note when comparing these results with your -own calculations: there might be some small rounding errors, which -when compounded lead to moderately different values.\bigskip - - -\noindent -\textbf{Moral:} Reflecting on our assumptions, we are over-estimating -our yield in many ways: first, who can know in 1978 about what will -turn out to be a blue chip company. Also, since the portfolios are -chosen from the current S\&P 500, they do not include the myriad -of companies that went bust or were de-listed over the years. -So where does this leave our fictional character Mr T.~Drumb? Well, given -his inheritance, a really dumb investment strategy would have done -equally well, if not much better.\medskip - -\end{document} - diff -r a2ac7e3fa330 -r 40657f9a4e4a cws/pre_cw01.pdf Binary file cws/pre_cw01.pdf has changed diff -r a2ac7e3fa330 -r 40657f9a4e4a cws/pre_cw01.tex --- a/cws/pre_cw01.tex Sat Oct 31 16:23:12 2020 +0000 +++ b/cws/pre_cw01.tex Sat Oct 31 16:47:46 2020 +0000 @@ -53,7 +53,7 @@ \subsection*{Hints} \noindent -\textbf{For Preliminary Part:} useful math operators: \texttt{\%} for modulo, \texttt{\&} for bit-wise and; useful +\textbf{For the Preliminary Part:} useful math operators: \texttt{\%} for modulo, \texttt{\&} for bit-wise and; useful functions: \mbox{\texttt{(1\,to\,10)}} for ranges, \texttt{.toInt}, \texttt{.toList} for conversions, you can use \texttt{List(...).max} for the maximum of a list, \texttt{List(...).indexOf(...)} for the first index of diff -r a2ac7e3fa330 -r 40657f9a4e4a pre_solition1/collatz.jar Binary file pre_solition1/collatz.jar has changed diff -r a2ac7e3fa330 -r 40657f9a4e4a pre_solition1/collatz.scala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pre_solition1/collatz.scala Sat Oct 31 16:47:46 2020 +0000 @@ -0,0 +1,50 @@ +// Basic Part about the 3n+1 conjecture +//================================== + +// generate jar with +// > scala -d collatz.jar collatz.scala + +object CW6a { // for purposes of generating a jar + +def collatz(n: Long): Long = + if (n == 1) 0 else + if (n % 2 == 0) 1 + collatz(n / 2) else + 1 + collatz(3 * n + 1) + + +def collatz_max(bnd: Long): (Long, Long) = { + val all = for (i <- (1L to bnd)) yield (collatz(i), i) + all.maxBy(_._1) +} + +//collatz_max(1000000) +//collatz_max(10000000) +//collatz_max(100000000) + +/* some test cases +val bnds = List(10, 100, 1000, 10000, 100000, 1000000) + +for (bnd <- bnds) { + val (steps, max) = collatz_max(bnd) + println(s"In the range of 1 - ${bnd} the number ${max} needs the maximum steps of ${steps}") +} + +*/ + +def is_pow(n: Long) : Boolean = (n & (n - 1)) == 0 + +def is_hard(n: Long) : Boolean = is_pow(3 * n + 1) + +def last_odd(n: Long) : Long = + if (is_hard(n)) n else + if (n % 2 == 0) last_odd(n / 2) else + last_odd(3 * n + 1) + + +//for (i <- 130 to 10000) println(s"$i: ${last_odd(i)}") +for (i <- 1 to 100) println(s"$i: ${collatz(i)}") + +} + + + diff -r a2ac7e3fa330 -r 40657f9a4e4a pre_templates1/collatz.jar Binary file pre_templates1/collatz.jar has changed diff -r a2ac7e3fa330 -r 40657f9a4e4a pre_templates1/collatz.scala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pre_templates1/collatz.scala Sat Oct 31 16:47:46 2020 +0000 @@ -0,0 +1,43 @@ +// Preliminary Part about the 3n+1 conjecture +//============================================ + +object CW6a { + +//(1) Complete the collatz function below. It should +// recursively calculate the number of steps needed +// until the collatz series reaches the number 1. +// If needed, you can use an auxiliary function that +// performs the recursion. The function should expect +// arguments in the range of 1 to 1 Million. + +def collatz(n: Long) : Long = ??? + + +//(2) Complete the collatz_max function below. It should +// calculate how many steps are needed for each number +// from 1 up to a bound and then calculate the maximum number of +// steps and the corresponding number that needs that many +// steps. Again, you should expect bounds in the range of 1 +// up to 1 Million. The first component of the pair is +// the maximum number of steps and the second is the +// corresponding number. + +def collatz_max(bnd: Long) : (Long, Long) = ??? + +//(3) Implement a function that calculates the last_odd +// number in a collatz series. For this implement an +// is_pow_of_two function which tests whether a number +// is a power of two. The function is_hard calculates +// whether 3n + 1 is a power of two. Again you can +// assume the input ranges between 1 and 1 Million, +// and also assume that the input of last_odd will not +// be a power of 2. + +def is_pow_of_two(n: Long) : Boolean = ??? + +def is_hard(n: Long) : Boolean = ??? + +def last_odd(n: Long) : Long = ??? + +} + diff -r a2ac7e3fa330 -r 40657f9a4e4a pre_testing1/collatz.scala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pre_testing1/collatz.scala Sat Oct 31 16:47:46 2020 +0000 @@ -0,0 +1,37 @@ +object CW6a { + +//(1) Complete the collatz function below. It should +// recursively calculate the number of steps needed +// until the collatz series reaches the number 1. +// If needed, you can use an auxiliary function that +// performs the recursion. The function should expect +// arguments in the range of 1 to 1 Million. +def stepsCounter(n: Long, s: Long) : Long = n match{ + case 1 => s + case n if(n%2==0) => stepsCounter(n/2,s+1) + case _ => stepsCounter(3*n+1, s+1) +} + +def collatz(n: Long) : Long = n match { + case n if(n>0) => stepsCounter(n,0) + case n if(n<=0) => stepsCounter(1,0) +} + + + +//(2) Complete the collatz_max function below. It should +// calculate how many steps are needed for each number +// from 1 up to a bound and then calculate the maximum number of +// steps and the corresponding number that needs that many +// steps. Again, you should expect bounds in the range of 1 +// up to 1 Million. The first component of the pair is +// the maximum number of steps and the second is the +// corresponding number. + +def collatz_max(bnd: Long) : (Long, Long) = { + val allCollatz = for(i<-1L until bnd) yield collatz(i) + val pair = (allCollatz.max, (allCollatz.indexOf(allCollatz.max) +1).toLong) + pair +} + +} diff -r a2ac7e3fa330 -r 40657f9a4e4a pre_testing1/collatz_test.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pre_testing1/collatz_test.sh Sat Oct 31 16:47:46 2020 +0000 @@ -0,0 +1,117 @@ +#!/bin/bash + +# to make the script fail safely +set -euo pipefail + + +out=${1:-output} + +echo -e "" > $out + +echo -e "Below is the feedback for your submission collatz.scala" >> $out +echo -e "" >> $out + + +# compilation tests + +function scala_compile { + (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala "$1" 2>> $out 1>> $out) +} + +# functional tests + +function scala_assert { + (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null) +} + +# purity test + +function scala_vars { + (egrep '\bvar\b|\breturn\b|\.par|ListBuffer|collection.mutable|util.control|new Array' "$1" 2> /dev/null 1> /dev/null) +} + + +# var, .par return, ListBuffer test +# +echo -e "collatz.scala does not contain vars, returns etc?" >> $out + +if (scala_vars collatz.scala) +then + echo -e " --> FAIL (make triple-sure your program conforms to the required format)\n" >> $out + tsts0=$(( 0 )) +else + echo -e " --> success" >> $out + tsts0=$(( 0 )) +fi + +### compilation test + + +if [ $tsts0 -eq 0 ] +then + echo -e "collatz.scala runs?" >> $out + + if (scala_compile collatz.scala) + then + echo -e " --> success" >> $out + tsts=$(( 0 )) + else + echo -e " --> SCALA DID NOT RUN COLLATZ.SCALA\n" >> $out + tsts=$(( 1 )) + fi +else + tsts=$(( 1 )) +fi + +### collatz tests + +if [ $tsts -eq 0 ] +then + echo -e "collatz.scala tests:" >> $out + echo -e " collatz(1) == 0" >> $out + echo -e " collatz(6) == 8" >> $out + echo -e " collatz(9) == 19" >> $out + + if (scala_assert "collatz.scala" "collatz_test1.scala") + then + echo -e " --> success" >> $out + else + echo -e " --> ONE OF THE TESTS FAILED\n" >> $out + fi +fi + +### collatz-max tests + +if [ $tsts -eq 0 ] +then + echo -e " collatz_max(10) == (19, 9)" >> $out + echo -e " collatz_max(100) == (118, 97)" >> $out + echo -e " collatz_max(1000) == (178, 871)" >> $out + echo -e " collatz_max(10000) == (261, 6171)" >> $out + echo -e " collatz_max(100000) == (350, 77031)" >> $out + echo -e " collatz_max(1000000) == (524, 837799)" >> $out + + if (scala_assert "collatz.scala" "collatz_test2.scala") + then + echo -e " --> success" >> $out + else + echo -e " --> ONE OF THE TESTS FAILED\n" >> $out + fi +fi + + +### last-odd tests + +if [ $tsts -eq 0 ] +then + echo -e " last_odd(113) == 85" >> $out + echo -e " last_odd(84) == 21" >> $out + echo -e " last_odd(605) == 341" >> $out + + if (scala_assert "collatz.scala" "collatz_test3.scala") + then + echo -e " --> success" >> $out + else + echo -e " --> ONE OF THE TESTS FAILED\n" >> $out + fi +fi diff -r a2ac7e3fa330 -r 40657f9a4e4a pre_testing1/collatz_test1.scala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pre_testing1/collatz_test1.scala Sat Oct 31 16:47:46 2020 +0000 @@ -0,0 +1,8 @@ + +import CW6a._ + +assert(collatz(1) == 0) +assert(collatz(6) == 8) +assert(collatz(9) == 19) + + diff -r a2ac7e3fa330 -r 40657f9a4e4a pre_testing1/collatz_test2.scala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pre_testing1/collatz_test2.scala Sat Oct 31 16:47:46 2020 +0000 @@ -0,0 +1,8 @@ +import CW6a._ + +assert(collatz_max(10) == (19, 9)) +assert(collatz_max(100) == (118, 97)) +assert(collatz_max(1000) == (178, 871)) +assert(collatz_max(10000) == (261, 6171)) +assert(collatz_max(100000) == (350, 77031)) +assert(collatz_max(1000000) == (524, 837799)) diff -r a2ac7e3fa330 -r 40657f9a4e4a pre_testing1/collatz_test3.scala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pre_testing1/collatz_test3.scala Sat Oct 31 16:47:46 2020 +0000 @@ -0,0 +1,4 @@ + +assert(CW6a.last_odd(113) == 85) +assert(CW6a.last_odd(84) == 21) +assert(CW6a.last_odd(605) == 341) diff -r a2ac7e3fa330 -r 40657f9a4e4a solutions1/collatz.jar Binary file solutions1/collatz.jar has changed diff -r a2ac7e3fa330 -r 40657f9a4e4a solutions1/collatz.scala --- a/solutions1/collatz.scala Sat Oct 31 16:23:12 2020 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -// Basic Part about the 3n+1 conjecture -//================================== - -// generate jar with -// > scala -d collatz.jar collatz.scala - -object CW6a { // for purposes of generating a jar - -def collatz(n: Long): Long = - if (n == 1) 0 else - if (n % 2 == 0) 1 + collatz(n / 2) else - 1 + collatz(3 * n + 1) - - -def collatz_max(bnd: Long): (Long, Long) = { - val all = for (i <- (1L to bnd)) yield (collatz(i), i) - all.maxBy(_._1) -} - -//collatz_max(1000000) -//collatz_max(10000000) -//collatz_max(100000000) - -/* some test cases -val bnds = List(10, 100, 1000, 10000, 100000, 1000000) - -for (bnd <- bnds) { - val (steps, max) = collatz_max(bnd) - println(s"In the range of 1 - ${bnd} the number ${max} needs the maximum steps of ${steps}") -} - -*/ - -def is_pow(n: Long) : Boolean = (n & (n - 1)) == 0 - -def is_hard(n: Long) : Boolean = is_pow(3 * n + 1) - -def last_odd(n: Long) : Long = - if (is_hard(n)) n else - if (n % 2 == 0) last_odd(n / 2) else - last_odd(3 * n + 1) - - -//for (i <- 130 to 10000) println(s"$i: ${last_odd(i)}") -for (i <- 1 to 100) println(s"$i: ${collatz(i)}") - -} - - - diff -r a2ac7e3fa330 -r 40657f9a4e4a templates1/collatz.jar Binary file templates1/collatz.jar has changed diff -r a2ac7e3fa330 -r 40657f9a4e4a templates1/collatz.scala --- a/templates1/collatz.scala Sat Oct 31 16:23:12 2020 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -// Preliminary Part about the 3n+1 conjecture -//============================================ - -object CW6a { - -//(1) Complete the collatz function below. It should -// recursively calculate the number of steps needed -// until the collatz series reaches the number 1. -// If needed, you can use an auxiliary function that -// performs the recursion. The function should expect -// arguments in the range of 1 to 1 Million. - -def collatz(n: Long) : Long = ??? - - -//(2) Complete the collatz_max function below. It should -// calculate how many steps are needed for each number -// from 1 up to a bound and then calculate the maximum number of -// steps and the corresponding number that needs that many -// steps. Again, you should expect bounds in the range of 1 -// up to 1 Million. The first component of the pair is -// the maximum number of steps and the second is the -// corresponding number. - -def collatz_max(bnd: Long) : (Long, Long) = ??? - -//(3) Implement a function that calculates the last_odd -// number in a collatz series. For this implement an -// is_pow_of_two function which tests whether a number -// is a power of two. The function is_hard calculates -// whether 3n + 1 is a power of two. Again you can -// assume the input ranges between 1 and 1 Million, -// and also assume that the input of last_odd will not -// be a power of 2. - -def is_pow_of_two(n: Long) : Boolean = ??? - -def is_hard(n: Long) : Boolean = ??? - -def last_odd(n: Long) : Long = ??? - -} - diff -r a2ac7e3fa330 -r 40657f9a4e4a testing1/collatz.scala --- a/testing1/collatz.scala Sat Oct 31 16:23:12 2020 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -object CW6a { - -//(1) Complete the collatz function below. It should -// recursively calculate the number of steps needed -// until the collatz series reaches the number 1. -// If needed, you can use an auxiliary function that -// performs the recursion. The function should expect -// arguments in the range of 1 to 1 Million. -def stepsCounter(n: Long, s: Long) : Long = n match{ - case 1 => s - case n if(n%2==0) => stepsCounter(n/2,s+1) - case _ => stepsCounter(3*n+1, s+1) -} - -def collatz(n: Long) : Long = n match { - case n if(n>0) => stepsCounter(n,0) - case n if(n<=0) => stepsCounter(1,0) -} - - - -//(2) Complete the collatz_max function below. It should -// calculate how many steps are needed for each number -// from 1 up to a bound and then calculate the maximum number of -// steps and the corresponding number that needs that many -// steps. Again, you should expect bounds in the range of 1 -// up to 1 Million. The first component of the pair is -// the maximum number of steps and the second is the -// corresponding number. - -def collatz_max(bnd: Long) : (Long, Long) = { - val allCollatz = for(i<-1L until bnd) yield collatz(i) - val pair = (allCollatz.max, (allCollatz.indexOf(allCollatz.max) +1).toLong) - pair -} - -} diff -r a2ac7e3fa330 -r 40657f9a4e4a testing1/collatz_test.sh --- a/testing1/collatz_test.sh Sat Oct 31 16:23:12 2020 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -#!/bin/bash - -# to make the script fail safely -set -euo pipefail - - -out=${1:-output} - -echo -e "" > $out - -echo -e "Below is the feedback for your submission collatz.scala" >> $out -echo -e "" >> $out - - -# compilation tests - -function scala_compile { - (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala "$1" 2>> $out 1>> $out) -} - -# functional tests - -function scala_assert { - (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null) -} - -# purity test - -function scala_vars { - (egrep '\bvar\b|\breturn\b|\.par|ListBuffer|collection.mutable|util.control|new Array' "$1" 2> /dev/null 1> /dev/null) -} - - -# var, .par return, ListBuffer test -# -echo -e "collatz.scala does not contain vars, returns etc?" >> $out - -if (scala_vars collatz.scala) -then - echo -e " --> FAIL (make triple-sure your program conforms to the required format)\n" >> $out - tsts0=$(( 0 )) -else - echo -e " --> success" >> $out - tsts0=$(( 0 )) -fi - -### compilation test - - -if [ $tsts0 -eq 0 ] -then - echo -e "collatz.scala runs?" >> $out - - if (scala_compile collatz.scala) - then - echo -e " --> success" >> $out - tsts=$(( 0 )) - else - echo -e " --> SCALA DID NOT RUN COLLATZ.SCALA\n" >> $out - tsts=$(( 1 )) - fi -else - tsts=$(( 1 )) -fi - -### collatz tests - -if [ $tsts -eq 0 ] -then - echo -e "collatz.scala tests:" >> $out - echo -e " collatz(1) == 0" >> $out - echo -e " collatz(6) == 8" >> $out - echo -e " collatz(9) == 19" >> $out - - if (scala_assert "collatz.scala" "collatz_test1.scala") - then - echo -e " --> success" >> $out - else - echo -e " --> ONE OF THE TESTS FAILED\n" >> $out - fi -fi - -### collatz-max tests - -if [ $tsts -eq 0 ] -then - echo -e " collatz_max(10) == (19, 9)" >> $out - echo -e " collatz_max(100) == (118, 97)" >> $out - echo -e " collatz_max(1000) == (178, 871)" >> $out - echo -e " collatz_max(10000) == (261, 6171)" >> $out - echo -e " collatz_max(100000) == (350, 77031)" >> $out - echo -e " collatz_max(1000000) == (524, 837799)" >> $out - - if (scala_assert "collatz.scala" "collatz_test2.scala") - then - echo -e " --> success" >> $out - else - echo -e " --> ONE OF THE TESTS FAILED\n" >> $out - fi -fi - - -### last-odd tests - -if [ $tsts -eq 0 ] -then - echo -e " last_odd(113) == 85" >> $out - echo -e " last_odd(84) == 21" >> $out - echo -e " last_odd(605) == 341" >> $out - - if (scala_assert "collatz.scala" "collatz_test3.scala") - then - echo -e " --> success" >> $out - else - echo -e " --> ONE OF THE TESTS FAILED\n" >> $out - fi -fi diff -r a2ac7e3fa330 -r 40657f9a4e4a testing1/collatz_test1.scala --- a/testing1/collatz_test1.scala Sat Oct 31 16:23:12 2020 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - -import CW6a._ - -assert(collatz(1) == 0) -assert(collatz(6) == 8) -assert(collatz(9) == 19) - - diff -r a2ac7e3fa330 -r 40657f9a4e4a testing1/collatz_test2.scala --- a/testing1/collatz_test2.scala Sat Oct 31 16:23:12 2020 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -import CW6a._ - -assert(collatz_max(10) == (19, 9)) -assert(collatz_max(100) == (118, 97)) -assert(collatz_max(1000) == (178, 871)) -assert(collatz_max(10000) == (261, 6171)) -assert(collatz_max(100000) == (350, 77031)) -assert(collatz_max(1000000) == (524, 837799)) diff -r a2ac7e3fa330 -r 40657f9a4e4a testing1/collatz_test3.scala --- a/testing1/collatz_test3.scala Sat Oct 31 16:23:12 2020 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ - -assert(CW6a.last_odd(113) == 85) -assert(CW6a.last_odd(84) == 21) -assert(CW6a.last_odd(605) == 341)